Detached Data in DLinq

Update: before trying the code pattern here,  see if you can use this  instead.

– Chris

I was reading two good blogs about Linq to SQL and ASP.Net applications  here and here.

Based on the pattern set up by Rocky Moore (see first link) I came up with this code. Using generics and a little bit of reflection in a base class.

Here is the base class

   public class detachableEntity<T> where T : detachableEntity<T>, new()

   {

      public void OnDataLoaded()

      {

         original = Clone();

      }

      public T original { get; set; }

 

      public T Copy()

      {

         return Copy((T)this);

      }

      public static T Copy(T Old)

      {

         T newItem = Clone(Old);

         newItem.OnDataLoaded(); // set the original state for the new object to the currect state

         return newItem;

      }

      public T Clone()

      {

         return Clone((T)this);

      }

      public static T Clone(T item)

      {

         if (item == null)

            return null;

 

         T newItem = new T();

         // copy all subclass properties.

         foreach (PropertyInfo prop in item.GetType().GetProperties())

         {

            PropertyInfo prop2 = item.GetType().GetProperty(prop.Name);

            prop2.SetValue(newItem, prop.GetValue(item, null), null);

         }

         //the two items now share the same orginal state object, fix this by

         //cloning the original state object on the item that to create a new original state

         //object for the new item

         if (item.original != null)

            newItem.original = item.original.Clone();

         return newItem;

      }

   }

In the partial classes created by Linq Designer here is how to add the base class

As the pattern is fixed, it is a good candidate for replace all in the partial class file.

   partial class Address : detachableEntity<Address>

   {

      partial void OnLoaded() { base.OnDataLoaded(); }

 

   }

and a usage example

static void Main(string[] args)

{

//Create new Entity

   Address home = new Address();

   //Create new data context

   AdventureWorksDataContext AW = new AdventureWorksDataContext();

   //Get Data

   home = AW.Addresses.First();

 

   // Disconnect Data Context

   AW = null;

 

   //Modify Data

   home.City = home.City + “AAA”;

 

   // New Data context

   AW = new AdventureWorksDataContext();

   //Attach Entity

   AW.Addresses.Attach(home, home.original);

   //Review Changes

   ChangeSet Changes = AW.GetChangeSet();

 

   //Update Data Source

   AW.SubmitChanges();

 

   //Dispose Data Context

   AW.Dispose();

   AW = null;

   //Dispose Entity

   home = null;

 

   //Create new Data Context

   using (AW = new AdventureWorksDataContext())

   {

      //Create new Entity

      Address NewHome = AW.Addresses.FirstOrDefault(addr => addr.City.Contains(“AAA”));

      //Modify Data (remove earlier changes)

      NewHome.City = NewHome.City.TrimEnd(new char[] { ‘A’ });

      //Submit Changes in the same context

      AW.SubmitChanges();

   }

}

This should be quite useful for detached applications.

-Chris