views:

598

answers:

1

I have a rather deep hierarchy of objects that I'm trying to persist with Entity Framework 4, POCO, PI (Persistence Ignorance) and Code First. Suddenly things started working pretty well when it dawned on me to not use the new() operator. As originally written, the objects frequently use new() to create child objects.

Instead I'm using my take on the Repository Pattern to create all child objects as needed. For example, given:

class Adam
{
  List<Child> children;
  void AddChildGivenInput(string input) { children.Add(new Child(...)); }
}

class Child
{
  List<GrandChild> grandchildren;
  void AddGrandChildGivenInput(string input) { grandchildren.Add(new GrandChild(...)); }
}

class GrandChild
{
}

("GivenInput" implies some processing not shown here)

I define an AdamRepository like:

class AdamRepository
{
    Adam Add() 
    { 
        return objectContext.Create<Adam>(); 
    }
    Child AddChildGivenInput(Adam adam, string input) 
    { 
        return adam.children.Add(new Child(...)); 
    }
    GrandChild AddGrandchildGivenInput(Child child, string input) 
    { 
        return child.grandchildren.Add(new GrandChild(...)); 
    }
}

Now, this works well enough. However, I'm no longer "ignorant" of my persistence mechanism as I have abandoned the new() operator.

Additionally, I'm at risk of an anemic domain model since so much logic ends up in the repository rather than in the domain objects.

After much adieu, a question:

Or rather several questions...

  • Is this pattern required to work with EF 4 Code First?
  • Is there a way to retain use of new() and still work with EF 4 / POCO / Code First?
  • Is there another pattern that would leave logic in the domain object and still work with EF 4 / POCO / Code First?
  • Will this restriction be lifted in later versions of Code First support?

Sometimes trying to go the POCO / Persistence Ignorance route feels like swimming upstream, other times it feels like swimming up Niagra Falls. Still, I want to believe...

+2  A: 

Hi Eric,

Here are a couple of points that might help answer your question:

In your classes you have a field for the children collection and a method to add to the children. EF in general (not just Code First) currently requires that collections are surface as properties, so this pattern is not currently supported. More flexibility in how we interact with classes is a common ask for EF and our team is looking at how we can support this at the moment

You mentioned that you need to explicitly register entities with the context, this isn’t necessarily the case. In the following example if GetAdam() returned a Adam object that is attached to the underlying context then the new child Cain would be automatically discovered by EF when you save and inserted into the database.

var adam = myAdamRepository.GetAdam();

var cain = new Child();

adam.Children.Add(cain);

~Rowan

Rowan Miller
@Rowan: Welcome to Stack Overflow. The fundamental problem is that I really have a deep object hierarchy, where each level knows how to create instances of objects of the next level. My understanding and experience is that I would have to manually walk my object hierarchy to attach all objects individually to an ObjectContext before they can be persisted. My application is quite complex but I'll try and distill it down to a simple, complete example. Won't happen today though, hopefully tomorrow.
Eric J.
@Eric J, that's not what I understood by Rowan's answer. To me it sounds like "If you add something to the public collection of related objects, then EF will automatically store that entity even if you haven't explicitly added it to the ObjectContext". This is consistent with the behaviour of LINQ to SQL.
Damian Powell