views:

659

answers:

2

I'm using VS2010, EF4 feature CTP (latest release), and POCO objects, such as the example below:

class Person
{
 public int ID { get; set; }
 public string Name { get; set; }
 public virtual IList<Account> Accounts { get; set; }
 ...
}

class Account
{
 public string Number { get; set; }
 public int ID { get; set; }
 ...
}

For the sake of brevity, assume context below is the context object for EF4. I have a dbml mapping between entity types and the database, and I use it like this with no problem:

Person doug = context.Persons.CreateObject();
doug.Name = "Doug";    
context.Add(doug);
context.Save();
doug.Accounts.Add(new Account() { Name = "foo" });
context.Save(); // two calls needed, yuck

At this point, the database has a Person record with the name "Doug", and an account record "foo". I can query and get those record back just fine. But if I instead try to add the account before I save the Person, the Accounts list is null (the proxy hasn't created an instance on that property yet). See the next example:

Person doug = context.Persons.CreateObject();
doug.Name = "Doug";
doug.Accounts.Add(new Account() { Name = "foo" }); // throws null reference exception
context.Add(doug);
context.Save();

Has anybody else encountered this? Even better, has anyone found a good solution?

+1  A: 

ISTM that if you expect the framework to do all this for you then you wouldn't really have a "POCO", would you? Take your Person class, with the code above. What would you expect the state of the Accounts property to be after construction, with no constructor, if the EF weren't involved? Seems to me that the CLR will guarantee them to be null.

Yes, proxies can initialize this when necessary for materialization of DB values, but in the EF, "POCO" actually means "Plain". Not "something packed with runtime-generated code which we pretend is 'Plain'".

Craig Stuntz
I've edited my question to clarify that I'm not asking about the constructor scenario, but the `context.Persons.CreateObject();` behavior. My confusion is that if the framework is going to 'own' those navigation properties after I save the object, why doesn't it do so when it creates the Entity instance? I have no problem putting collection initialization in the constructors of my Entities, but if the framework is expecting those collections to be `null`, it seems I'm putting the object into a bad state.
Douglas R
+1  A: 

Yes and yes!

When you new the POCO up (as opposed to CreateObject from the Context), no proxies are provided for you. This may seem obvious, but I had to explicitly remind myself of this behavior when chasing a similar issue down. (I know this isn't the situation you described in the question, but the overall issue should be acknowledged).

Initializing collections in the constructor of the POCO does not interfere with proper EF4 proxy lazy-loading behavior, from what I've observed in my own testing.

OK, all this being said, I now see your comment to the previous answer -- why don't I have a proxied Addresses collection when I request a new Person from my context? Do you have lazy loading enabled on the context? Seeing how we're dealing with navigation properties, I could see where having lazy loading turned off may make a difference in this situation.

kdawg