Reputation: 13
I have an application where I use POCO classes and I'm getting an error when I try to set a relationship between a new object and a persisted object.
I have these classes: SecurityUser
and SecurityGroup
. SecurityUser
has a property Group_ID
where I can set the ID for the user group and a property SecurityGroup
where I can set the object itself. When I try to set a new SecurityGroup
for this property I get the "null reference" exception on the POCO class. Here's an example of my code:
using (SecurityEntities context = new SexurityEntities(connectionString))
{
SecurityUser user = context.SecurityUsers.SingleOrDefault(cond => cond.User_ID == 1);
SecurityGroup group = new SecurityGroup();
user.SecurityGroup = group;
context.SecurityGroups.AddObject(group);
context.SaveChanges();
}
When I do this without using the entity framework without the POCO classes, everything goes well, but with POCOs it doesn't.
Upvotes: 1
Views: 308
Reputation: 177133
It's one of those ugly relationship fixup problems which are causing trouble with EF 4 POCOs every now and then.
If you take a look at the classes created by the POCO generator you'll see a region called "Association Fixup" containing some methods like FixupSecurityGroup
or similar called from property setters of your POCOs. I could reproduce your problem but even after debugging I couldn't find exactly the point where it goes wrong in these fixup methods. So, I cannot explain why your code doesn't work.
But I found two solutions which work:
1) Don't create the group with new
but use the CreateObject
method:
SecurityUser user = context.SecurityUsers
.SingleOrDefault(cond => cond.User_ID == 1);
SecurityGroup group = context.SecurityGroups.CreateObject();
user.SecurityGroup = group;
context.SaveChanges();
(I've removed AddObject
. It's not necessary because EF recognizes that the group is new and creates an INSERT statement, but removing AddObject
alone doesn't fix the problem.)
Your POCO properties are virtual
and EF will create a dynamic proxy for the SecurityUser
when you load it from the DB. Apparently for some reason a dynamic proxy also for the SecurityGroup
you create is required, otherwise we get your null reference exception. CreateObject
will create this proxy.
2) Alternatively you can turn off proxy creation:
context.ContextOptions.ProxyCreationEnabled = false;
SecurityUser user = context.SecurityUsers
.SingleOrDefault(cond => cond.User_ID == 1);
SecurityGroup group = new SecurityGroup();
user.SecurityGroup = group;
context.SaveChanges();
Now, user
is no dynamic proxy and the code also works when you create the group with an ordinary new
operator.
Upvotes: 1