Linq2Sql:管理DataContext

时间:2008-12-19 11:24:18

标签: c# asp.net linq-to-sql

以下代码不能用作

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();
}

这样做不行,我收到错误信息。 “尝试附加或添加一个非新的实体,可能是从另一个DataContext加载的。这是不受支持的。”

如何在整个应用程序中使用DataContexts,这样您就不需要传递引用?

什么

6 个答案:

答案 0 :(得分:5)

他们的确意味着'这不受支持'。未实现附加到从其他数据上下文获取的对象。

这个问题有很多解决方法,推荐的方法是序列化对象,但这不容易,也不干净。

我发现最简单的方法是使用readonly DataContext来获取这样的对象:

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

从此上下文获取的对象可以附加到另一个上下文,但仅适用于某些场景。

答案 1 :(得分:4)

PLINQO框架为所有实体生成分离,以便在不接收错误的情况下轻松分离和重新附加对象。

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();
}

这篇文章介绍了如何实现分离。 http://www.codeproject.com/KB/linq/linq-to-sql-detach.aspx

答案 2 :(得分:1)

是的。这就是它的工作原理。

您已为此asp.net添加了标签,因此我猜这是一款网络应用。也许你想要每个请求一个datacontext?

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

(P.S。在WinForms中要难得多了!)

答案 3 :(得分:0)

我已经创建了数据访问类,它封装了与Linq2Sql的所有通信。 这些类有自己的datacontext,用于对象。

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(); 
    }
}

当然,只要您需要对象,就需要保持此对象的实例化。

检查是否只更改了rigth对象是有点麻烦的,你可以制作像

这样的方法
void ChangeClientValue(int clientId, int value);

但这可能会成为很多代码。

附加和分离是Linq2Sql的一个缺失功能​​,如果你需要大量使用它,你可能会使用Linq2Entities。

答案 4 :(得分:0)

您需要处理对象版本控制。

如果实体声明版本成员或没有更新检查策略,则实体只能在没有原始状态的情况下附加修改。

因此,如果没有提供时间戳成员或其他“版本控制”机制,LINQ无法确定数据是否已更改 - 因此您看到错误。

我通过在表格中添加timestamp列来解决此问题,但还有其他方法。 Rick Strahl写了一些关于这个问题的正确articles

另外,请参阅thisthis了解更多信息。

答案 5 :(得分:0)

我看了一眼,发现只要原始的DataContext被处理掉它似乎工作正常。

尝试使用()包装DataContext,并确保在附加到第二个DataContext后进行更改?它对我有用..

        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();
            }
        }