views:

140

answers:

3

Using Linq-to-Sql:

MyClass obj;
...
// need to delete this object
dataContext.GetTable(obj.GetType()).DeleteOnSubmit(obj);

BUT

I don't know whether or not obj has been attached to the data context. And if it hasn't, that last call to DeleteOnSubmit throws an exception.

There has to be an easy way of telling whether obj is attached to dataContext - but I can't see anything obvious.

How do you do it?

A: 

Link2SQL, I assume? This should be apparent from your code. Do you really need to query the state dynamically at runtime? obj is only attached if you obtained it from your dataContext.

I asked a similar question a while ago. Maybe Robert Harvey's comments are helpful to you.

cdonner
This is incorrect. You can also manually instantiate an object an attach it to the context.
Adam Robinson
yes- Linq2Sql - sorry, will update question. As for part 2 of your answer: in the context in which my code is being written, the object is being passed in as a parameter, and I don't have any direct way of knowing whether it's already attached to the data context; can't make any assumptions.
Shaul
I found myself fighting this a lot, until I finally accepted that the best way of working with Linq is doing data manipulation with a local scope only. If my objects need to have a wider scope, for instance survive a post-back in a web app in the session, I use double-buffering, i.e. once I have a detached object, I get a fresh version from the db and copy the members before I update it. This alleviates these kind of issues.
cdonner
@Adam: Why does a manually instantiated object need to be attached? The only thing you can do with it is inserts, and it will not throw an exception when you insert it.
cdonner
@Adam, with all due respect, my response is not incorrect. Nowhere did I say that you cannot manually instantiate an object. He is trying to delete an object, and if you delete an object, you have to first obtain it from your datacontext.
cdonner
@cdonner: It's incorrect where it says "obj is only attached if you obtained it from your dataContext.", as you can instantiate an object and attach it manually. This is used for attaching objects that are created outside of a `DataContext` (through serialization, for example) that are not new entities. See http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/384a1c03-3acf-43ef-9a25-b84f93025e63/
Adam Robinson
If you instantiate an object it is not attached. We are in agreement, since this is deterministic.
cdonner
@cdonner: Yes...and you can then subsequently attach it. In that manner you now have an attached object that you did not obtain from the DataContext.
Adam Robinson
+1  A: 

While you may want to take a look at your design, since this sort of thing should be something that you can figure out deterministically, it's possible to do.

Unfortunately, the exact call to determine if the object is attached (or, in L2S's internal nomenclature, "tracked") requires that you call Context.Services.ChangeTracker.GetTrackedObject, which is internal. The closest thing I can see is calling Table.GetOriginalEntityState, passing in the entity in question. If the return value is null, then the object is untracked (unattached). If the return value is non-null, then the object is tracked (attached).

Note that I haven't actually tested this, but looking at the code in Reflector gives me the impression that this should work for you.

Adam Robinson
+1 + answer credit - thank you!
Shaul
A: 

One way you can tell if an object is attached to a data context is by looking at the PropertyChanging and PropertyChanged events.

I have a method on my entities to detach them as follows:


public virtual void Detach()
{
   PropertyChanging = null;
   PropertyChanged = null;
} 

So, if these two properties are not null, the object is attached.

Randy

Randy Minder
This, unfortunately, won't work unless you're coding within the class itself. Even descendants won't be able to use this method.
Adam Robinson