Linq to Sql designed for Asp.Net, NOT Desktop apps RRS feed

  • Question


    Good Morining,

     I've read many posts on how to refresh object in a Linq DataContext. My conculsion is that it's not possible to do it right and it's better to throw away the entire context before using it again. Try do the following ops:


    - Get an entity let's say Table with associated TableColumns.

    - try to add a TableColumn in the list of columns for the table

    - refresh the DataContext

    - there you have the first exception saying that linq cannot get the object back (of course, it's not in the db!)

    - I've read someone saying to remove the newly added object from the collection before calling Refresh()

    - well that worked but any subsequent call to Refresh(someotherobject) or SubmitChanges() fail.


    I've also read someone (MVP) saying that linq was designed with Asp.Net scenario in mind, that is, the context last for the duration of the request.

    I'm working on a Windows application which allows the user to do modification to entities in a session. The user can discard some changes and confirm some other. I definately cannot use the DataContext for this secenario due to the Refresh problem. I must go back to DataSets, dear old DataSets!


    Is there anyone that can explain why the DataContext is behaving this way?






    Friday, July 11, 2008 7:35 AM


  • I'd disagree with the statement that LINQ to SQL was designed with ASP.NET in mind. The DataContext behavior follows a standard pattern for ORMs - it's called the Unit of Work pattern. nHibernate's equivalent abstraction is an ISession, and it behaves in the same manner.


    A unit of work manages a single business conversation (although sometime you'll hear the term "business transaction", which can be confusing because it makes you think of database transactions), and it just so happens that it is easy to associate a unit of work with a single web request, because that web request generally represents a single business conversation (updating a customer's details by posting back a web form, for example). I agree - in a smart client app it is a little more difficult to define your logical conversations.


    You can think of a DataSet / DataTable as a unit of work, too. It tracks all the changes you want to apply to the data during a business conversation, and via the data adapters, records the data changes in the database using INSERT, UPDATE, DELETE commands. The primary difference for your scenario is that a DataTable has some built in versioning features for data - it tracks both the original version and current version, making it easiest to perform an "undo" (RejectChanges on a DataRow or DataTable, which is what I assume you were doing before).


    LINQ to SQL entities don't version themselves. If you want similar functionality you'll have to store the original property values for each entitiy. When the user wants to "undo" an operation you'll grab the original values and put them back into the entity, avoiding a call to Refresh. Perhaps grab the values from a second unit of work, or also look at the Memento pattern - it can give your user multi-level undo operations, which is useful on complex forms. Ultimately though, you'll have to pick which solution is easiest for you to develop and maintain. You might rethink the design and find easier ways to use real objects and LINQ to SQL, too.



    Saturday, July 12, 2008 7:29 PM