C# – Round-tripping SubSonic DAL objects with WCF

cdatabasesubsonicwcf

Question: How do I preserve "dirtiness" of SubSonic objects when they are sent back and forth across a Windows Communication Foundation service?

To wit:

I have a WCF service call that returns a collection of SubSonic (2.2) objects, like so:

// WCF server side
public MyObjectCollection GetAllMyObjects()
{
   // Retrieve a MyObjectCollection (SubSonic-generated class) from the DB
   return DB.Select().From<MyObject>.ExecuteAsCollection<MyObjectCollection>();
}

and another that lets the client save them:

// WCF server side
public void SaveAllMyObjects(MyObjectCollection objs)
{
   objs.SaveAll();
}

On the WCF client side, I retrieve this collection (via the generated WCF proxy), I modify some of its members, then I save it:

// WCF client side
MyObject[] allObjects = myWcfClient.GetAllMyObjects();
allObjects[3].SomeProperty = "Some other value";
myWcfClient.SaveAllMyObjects(allObjects);

What happens, however, is that the SubSonic "objs.SaveAll()" call does not save anything, as it does not "realize" that objs[3] has been modified, i.e. nobody has flipped the "dirty" bit on that column.

Is this an anti-pattern I'm implementing, or is this a sensible way of doing things? If so, how can I convince SubSonic to mark my objects as dirty when they go across the WCF wire?

Best Answer

I have found a solution, but it feels hacky, and it would be great for it to be vetted by someone who knows more about SubSonic than I. The idea is that in the server-side code that saves MyObjectCollection I'd create as many new MyObject instances as were passed in, set the correct primary key, fake SubSonic into believing they were just loaded from the DB, populate the new objects from the old ones, then save the new collection. So the method above looks like this:

// WCF server side
public void SaveAllMyObjects(MyObjectCollection objs)
{
   MyObjectCollection fakeColl = new MyObjectCollection();
   foreach (var oneObj in objs)
   {
       var oneFakeObj = new MyObject();
       oneFakeObj.Id = oneObj.Id;    // Primary key
       // Pretend oneFakeObj was just loaded from the DB
       oneFakeObj.IsNew = False;
       oneFakeObj.IsLoaded = True;
       // Copy all column values
       foreach (var col in MyObject.Schema.Columns)
       {
           oneFakeObj.SetColumnValue(col.ColumnName, oneObj.GetColumnValue(col.ColumnName));
       }
       fakeColl.Add(oneFakeObj);
  }
  fakeColl.SaveAll();
}
Related Topic