Configuring ORM’s through fluent api calls is relatively new to me. For the last three years or so I’ve been using EF1 and Linq-To-Sql as my data modeling tools of choice. My first exposure to a code-first ORM tool came in June when I started working with Fluent NHibernate. As interesting as that has been, I hadn’t really be faced with the issue of proper configuration because I’ve had someone on our team that does it easily. This weekend I started working on a sample project using the EF4 CTP, and the biggest stumbling block has been modeling the relationships.
The context code is a SCRUM process management app I’m writing. Here’s the model:
The relationship I tried to model was the one between Project and Story via the Backlog property. Since “Project” is the first entity I needed to write, my natural inclination was to model the relationship to “Story” first.
I knew that “Story” would be slightly more complex because it has two properties that map back to “Project.” These are the “Project” property ,and the “ProjectId” property. Some of the EF4 samples I found refer to a “Relationship” extension method that I was unable to find in the API, so I was fairly confused. I finally figured out what I needed to do by reading this post from Scott Hanselman, though he doesn’t specifically highlight the question I was trying to answer.
This is the mapping code I created for “Story:”
and this is the code I’m using to create a new Story for a project:
When I tried to save the story, the data context threw various exceptions. I thought I could avoid the problem by rewriting the code so that I was just adding the story directly to the “Stories” table on the DataContext (which I think will ultimately be the right thing as it saves an unnecessary database call), but that would have been hacking around the problem and not really understanding what was wrong with what I was doing. It just took some staring at Scott Hanselman’s code sample for awhile to realize what was wrong with my approach. Before I explain it, let me show you the mapping code that works.
Notice what’s missing? I completely yanked the mapping of “Project->Stories” from the “Project” model’s perspective. Instead, I map the one-to-many relationship from the child-entity’s perspective, i.e., “Story.” Here’s how to read the mapping.
The key here is understanding that one-to-many relationships must be modeled from the perspective of the child-entity.