Linq2Sql: DataContext Management

The following code does not work as

public void Foo() { CompanyDataContext db = new CompanyDataContext(); Client client = (select c from db.Clients ....).Single(); Bar(client); } public void Bar(Client client) { CompanyDataContext db = new CompanyDataContext(); db.Client.Attach(client); client.SomeValue = "foo"; db.SubmitChanges(); } 

This does not work, I get an error. "An attempt was made to connect or add an object that is not new, it may have been loaded from another DataContext. This is not supported."

How do you work with DataContexts throughout the application, so you do not need to pass a link?

what

+4
source share
6 answers

The PLINQO framework generates debugging for all objects, which makes it easy to disconnect and reconnect objects without receiving this error.

 public void Foo() { CompanyDataContext db = new CompanyDataContext(); Client client = (select c from db.Clients ....).Single(); // makes it possible to call detach here client.Detach(); Bar(client); } public void Bar(Client client) { CompanyDataContext db = new CompanyDataContext(); db.Client.Attach(client); client.SomeValue = "foo"; db.SubmitChanges(); } 

Here's an article describing how the breakaway was done. http://www.codeproject.com/KB/linq/linq-to-sql-detach.aspx

+4
source

They really mean it: "It is not supported." Binding to an object obtained from another data context is not implemented.

There are a number of ways to solve this problem, the recommended way is to serialize objects, but this is not an easy and difficult approach.

The easiest approach I have found is to use readonly DataContext to select such objects:

  MyDataContext dataContext = new MyDataContext() { DeferredLoadingEnabled = false, ObjectTrackingEnabled = false }; 

Objects derived from this context may be attached to a different context, but apply only to certain scenarios.

+5
source

Yeah. How it works.

You checked this asp.net, so I assume this is a web application. Maybe you need one datacontext for the query?

http://blogs.vertigo.com/personal/keithc/Blog/archive/2007/06/28/linq-to-sql-and-the-quote-request-scoped-datacontext-quote-pattern.aspx

(PS This is much more complicated in WinForms!)

+1
source

I created data access classes that encapsulate all communication with Linq2Sql. These classes have their own datacontext, which they use on their objects.

 public class ClientDataLogic { private DataContext _db = new DataContext(); public Client GetClient(int id) { return _db.Clients.SingleOrDefault(c => c.Id == id); } public void SaveClient(Client c) { if (ChangeSetOnlyIncludesClient(c)) _db.SubmitChanges(); } } 

Of course, you will need to support this object provided that you need objects.

Checking if only the rigth object has been modified is a bit of a bother; you could do methods like

 void ChangeClientValue(int clientId, int value); 

but it can become a lot of code.

Attaching and detaching is the missing feature of Linq2Sql, if you need to use a lot, maybe you are using Linq2Entities.

0
source

You need to handle object versioning.

An object can only be attached as modified without an initial state if it declares a member of the version or does not have an update check policy.

So, if there is no timestamp element or other β€œversion control” mechanism, there is no way for LINQ to determine if this data has changed - hence the error you see.

I solved this problem by adding a timestamp column to my tables, but there are other ways. Rick Streyl has written several worthy articles on this very issue.

Also see this and this for a bit more information.

0
source

I took a look at this and found that it worked fine while the original DataContext was deleted.

Try wrapping the DataContext with () and making sure your changes happen after joining the second DataContext? It worked for me.

  public static void CreateEntity() { User user = null; using (DataClassesDataContext dc = new DataClassesDataContext()) { user = (from u in dc.Users select u).FirstOrDefault(); } UpdateObject(user); } public static void UpdateObject(User user) { using (DataClassesDataContext dc = new DataClassesDataContext()) { dc.Users.Attach(user); user.LastName = "Test B"; dc.SubmitChanges(); } } 
0
source

All Articles