none
Disconnected Model? RRS feed

  • Question

  • Hi,

     

          What the best way to work in a disconnected mode using L2S? I am having a WCF service which throws a bunch of records. I am moving those bunch of records to an observable collection & binding it to XBAP controls. The client may modify / add / delete the objects. How do I save them back?

     

    http://www.codeplex.com/LINQ2SQLEB/Release/ProjectReleases.aspx?ReleaseId=13243 was one solution I found.

     

    Are there any best practicies here?

     

    Thanks in advance.

     

    Life is so beautiful!!!

     

    Success,

     

    Niraj

    Thursday, May 15, 2008 8:08 AM

Answers

  • Hey Niraj,

     

    No of course I agree a built in mechanism wouldn't cause much harm(but it will eventually some, based on the design), but imho in this case the scenarios that you need to cover is not that much. The work that is done in the link you have sent is pretty good, but my fear is you may end up involving lots of other things that you don't need. 

     

    I don't like a stateful DAL aproach as a developer too, but I'd like my hands in the state management (that's one of the reasons that I am disconnected from the context, isnt it ?) rather then delegating it since I can have some specific scenarios that I want to tweak.

     

    For the example you provided, there is no need to hold a second list since you can get the benefit of lambda expressions very impressively. Here is a code that I used in my recent project to bind a grid:

     

    Code Snippet

    ///

    /// Binds the grid.

    ///

    /// The line numbers for this product.

    private void BindGrid(IList<dsm_line_nr> lineNumbersForThisProduct)

    {

    productLineNumbersGridView.DataSource = lineNumbersForThisProduct.Where<LineNumber>(lnr => lnr.EntityStatus != EntityStatus.Deleted).ToList<LineNumber>();

    productLineNumbersGridView.DataBind();

    }

     

     

     

    As you see I am binding the entities whose state is "Not deleted" and this is no more than 1 line of code. When I am deleting these line numbers I empoy the following(context is my data context, sub is the parent of my collection):

     

    Code Snippet

    context.LineNumbers.AttachAll<LineNumber>(sub.LineNumbers.Where<LineNumber>(lnr => lnr.EntityStatus == EntityStatus.Updated || lnr.EntityStatus == EntityStatus.Deleted), true);

     

    context.LineNumbers.DeleteAllOnSubmit<LineNumber>(sub.LineNumbers.Where<LineNumber>(lnr.EntityStatus == EntityStatus.Deleted));

     

     

     

    So there we are, very clean entity management with a very few lines of codes. A DisconnectedDataContext can be nice for the future, but for the time being that's what we have lazy boy Smile

     

    Hope it helps.

     

    Sidar

     

    Thursday, May 15, 2008 2:12 PM

All replies

  • that's the only one i know about. that's from a mate of mine, here at work Smile

    Thursday, May 15, 2008 8:17 AM
  • Hey Niraj,

    When disconnected, you need to keep track of your objects and manage their state. When you come back to your dal, you need to know what objects need to be updated, deleted, created or retrieved (retrieve is not much a problem)

    For inserts - You need to use InsertOnSubmit(entity)

    For Update - You need to Attach(entity, true) your object to the context's table. This second parameter indicates that you are attaching the object as modified so an update statement will be generated for it even if no changes occur after this point.

    For Delete - If you want to delete disconnected objects, you first need to attach them, then call DeleteOnSubmit(entity) . The reason for this is DeleteOnSubmit can not delete an untracked entity, except inserts context needs to know about every other operation to succeed in generating the query.

    I have written this article a while ago, may help on what you are doing: http://www.sidarok.com/web/blog/content/2008/04/21/a-brief-introduction-to-linq-to-sql.html


    Thursday, May 15, 2008 9:14 AM
  • Hello Sidar,

     

           Thanks for reply. But my question revolves around your first line, remaining things are quite simple.

     

    When disconnected, you need to keep track of your objects and manage their state. When you come back to your dal, you need to know what objects need to be updated, deleted, created or retrieved

     


    How do you do the above? Are there any recommended ways of doing it, something which MS endorses? Not sure how they can keep quiet on this important aspect. Though they are not able to make it even with SP1 they should have published some guidance on doing it.

     

    Life is so beautiful!!!

     

    Success,

     

    Niraj

    Thursday, May 15, 2008 11:19 AM
  •  

    I don't really know what MS endorses, but here is what I do and is proven good according to my experience with a couple of other ORM Mappers existed before Linq to SQL (NHibernate, Wilson ORM to name a few - Those mappers are not doing that kind of tracking in disconnected mode either!).

     

    I am extending the entities in partial class from my BaseEntity, which holds an enumeration as status (EntityStatus.New, EntityStatus.Updated, EntityStatus.Deleted). When I do a change, accordingly I update the status and in my dal, I have a switch case statement for this field that performs the relevant operation. i.e Let's say that I need to delete an entity from a collection, instead of removing it instantly form the collection I mark it as "Deleted" and I perform DeleteOnSubmit in the collection for the entities who are marked as deleted:

     

    IEnumerable collection;

     

    ...

    ...

     

    context.DeleteAllOnSubmit<MyEntity>(collection.Where<MyEntity>(entity => entity.EntityStatus == EntityStatus.Deleted));

     

    I follow the same approach for inserts and updates (InsertAllOnSubmit and AttachAll generic methods respectively).

     

    This is what I do, hope it helps.

     

    Thanks,

     

    Sidar

    Thursday, May 15, 2008 12:56 PM
  • Hi Sidar,

     

             I know I have been lazy here Smile. But guess my work doesn't permit to think of all scenarios. For e.g. when you do a soft delete by just changing the enum on client side, how do you make the item look deleted to end user? You need to have a seperate collection where all those deleted items are stored & reattach them on server side. Moreover changing the state manually is also a cumbersome job.

     

            Also if you can paste some code it will be great (though I am getting what you are trying to put across).

     

    Life is so beautiful!!!

     

    Success,

     

    Niraj

    Thursday, May 15, 2008 1:45 PM
  • Hey Niraj,

     

    No of course I agree a built in mechanism wouldn't cause much harm(but it will eventually some, based on the design), but imho in this case the scenarios that you need to cover is not that much. The work that is done in the link you have sent is pretty good, but my fear is you may end up involving lots of other things that you don't need. 

     

    I don't like a stateful DAL aproach as a developer too, but I'd like my hands in the state management (that's one of the reasons that I am disconnected from the context, isnt it ?) rather then delegating it since I can have some specific scenarios that I want to tweak.

     

    For the example you provided, there is no need to hold a second list since you can get the benefit of lambda expressions very impressively. Here is a code that I used in my recent project to bind a grid:

     

    Code Snippet

    ///

    /// Binds the grid.

    ///

    /// The line numbers for this product.

    private void BindGrid(IList<dsm_line_nr> lineNumbersForThisProduct)

    {

    productLineNumbersGridView.DataSource = lineNumbersForThisProduct.Where<LineNumber>(lnr => lnr.EntityStatus != EntityStatus.Deleted).ToList<LineNumber>();

    productLineNumbersGridView.DataBind();

    }

     

     

     

    As you see I am binding the entities whose state is "Not deleted" and this is no more than 1 line of code. When I am deleting these line numbers I empoy the following(context is my data context, sub is the parent of my collection):

     

    Code Snippet

    context.LineNumbers.AttachAll<LineNumber>(sub.LineNumbers.Where<LineNumber>(lnr => lnr.EntityStatus == EntityStatus.Updated || lnr.EntityStatus == EntityStatus.Deleted), true);

     

    context.LineNumbers.DeleteAllOnSubmit<LineNumber>(sub.LineNumbers.Where<LineNumber>(lnr.EntityStatus == EntityStatus.Deleted));

     

     

     

    So there we are, very clean entity management with a very few lines of codes. A DisconnectedDataContext can be nice for the future, but for the time being that's what we have lazy boy Smile

     

    Hope it helps.

     

    Sidar

     

    Thursday, May 15, 2008 2:12 PM
  • Hi Sidar,

     

           With some motivation I am all set to build one. One query if you can throw some light. If I have a object graph, let say a department with many classes (basically a association relationship - one to many), I am displaying that in UI. Now the user can manipulate the graph in his own way e.g. add a class, add a department, alter either of them or delete either of them. How to best update an object graph in disconnected mode?

     

    Thanks in advance!!!

     

    Life is so beautiful!!!

     

    Success,

     

    Niraj

     

    Saturday, May 17, 2008 4:44 PM
  • Hey Niraj,

     

    So let's say you have customer =>* orders . When you add a class, you might add the entity status with new :

     

    Code Snippet

    customer.Orders.Add(new Order()

                                    {

    // do all the mapping you need

    Status = EntityStatus.New,

                                    });

     

     

     

    And for update, for delete, instead of doing a RemoveAt(i) or Remove from the collection, just mark it as deleted :

     

     

    Code Snippet

    customer.Orders[indexToDelete].Status = EntityStatus.Deleted;

     

     

     

    And for instance when you need a count of the records UI,or binding it to a control, you only need to ignore the Deleted ones like these:

     

    Code Snippet
    var listToBind = customer.Orders.Where(ord => ord.Status != EntityStatus.Deleted);

     

     

     

    And for the updates, when you update, you set the status to Updated.

     

    So at the end, you'll have an entity set collection, which has Entities with status = None, New, Updated, Deleted.This means that you now know what to attach, insertonsubmit, deleteonsubmit.

     

    This way you can also customize your behavior on what to do, i.e you might not want to mark any Orders if you are going to delete the Customer parent of it.

     

    Hope this is enough for proceeding a bit.

     

    Thanks,

     

    Sidar

    Monday, May 19, 2008 8:52 AM