Friday, April 17, 2009

Working with detached entities and Linq to Sql

On my current project we are using Linq to Sql, and as it is a web application are working with the DataContext in limited scope only during data operations. This means that objects generally need to be attached to the context in order for all operations to succeed (all related parent objects must be attached when inserting children, changed objects before updates/deletes)

One annoyance I have is that I can't really tell if I should attach the object, insert it, or just update it. If every operation is done in an entirely atomic fashion, or you associate objects by key values only; this can be avoided. Yet that robs me of the features I like such as adding any number of new objects, associate object instances together and let the context figure out the order of operations. With fairly atomic data operations defined in our data class we end up blind to the state of the objects when dealing with a new context.

To help out with this I have created the following extension on DataContext...
public static class DCExtensions{
 public static void SafeAttach<T>(this DataContext context
, T entity)
where T : class
{
Table<T> entityTable = context.GetTable<T>();
if (entityTable == null)
return;
T instance = entityTable.GetOriginalEntityState(entity);
if (instance == null)
{
if (!entityTable.Contains(entity))
entityTable.InsertOnSubmit(entity);
else
entityTable.Attach(entity);
}
}
}

I can then have a method like the following that isn't concerned with entity state:


internal ChildObject AddAssociation(ParentObject1 parent1
, ParentObject2 parent2)
{
using (var dc = new MyDataContext())
{
dc.SafeAttach(parent1);
dc.SafeAttach(parent2);
ChildObject child = new ChildObject();
child.Parent1 = parent1;
child.Parent2 = parent2;
dc.ChildObjects.InsertOnSubmit(child);
dc.SubmitChanges();
return child;
}
}
Submit this story to DotNetKicks