3
votes

After creating a new object (Foo), I set the key (BarId) for an EntityRef association property (Bar). I then want to insert the new object into the database, and be able to access the lazy-loaded child object afterward.

Unfortunately, the lazy-loading property returns null after the call to InsertOnSubmit(). It returns the correct object if I instead Attach() the object to the data context, however.

Here's code that successfully inserts my new object into the database, but doesn't correctly setup lazy-loading for the child Bar property:

var foo = new Foo();
foo.BarId = 123;
context.GetTable<Foo> ().InsertOnSubmit( foo );
foo.Bar.Something();    // throws NullReferenceException

Here, the Bar object is properly loaded:

var foo = new Foo();
foo.BarId = 123;
context.GetTable<Foo> ().Attach( foo );
foo.Bar.Something();    // method is called on lazy-loaded Bar object

Calling Attach before InsertOnSubmit causes the latter to throw a "Cannot add an entity that already exists" exception.

So, is this a bug in LINQ-to-SQL, where inserted objects are not properly attached to the data context?

How do I fix this?

1
When using InsertOnSubmit, you need SaveChanges to submit the new object to the data store. This could be the problem, since creating a new data item does not innately associate a data context to it (to lazy load from) until the object is populated by the context (I think). - Nick Larsen
I see. Unfortunately, I've built a security layer on top of my data context that checks object/user permissions before calling SubmitChanges(). That code needs to access certain properties of my objects, including ones that are lazy-loaded. Whether that is a good idea is questionable, but it's what I have to work with now. - MikeWyatt
@NickLarsen: I just tested this, and you are correct. The lazy-loading works after calling SubmitChanges(). - MikeWyatt

1 Answers

3
votes

I would set the Bar property instead of the BarId property of your Foo class. In my opinion what Linq-to-sql does wrong here is to have the BarId property in the first place. It doesn't add any value and It goes against core principals of OOP. So, I would change your code to something like this:

var foo = new Foo();
foo.Bar = //get bar with id: 123;
context.GetTable<Foo> ().InsertOnSubmit(foo);
foo.Bar.Something();