当我处理上下文时,为什么LINQ 2 SQL会尝试获取子关系?

时间:2010-11-04 13:47:35

标签: linq-to-sql c#-3.0 datacontractserializer objectdisposedexception

我在我的一个项目中使用LINQ 2 SQL,并且我有很多关系客户 - > Documents1,Documents2,Documents3,Address,Invoices等....

使用LoadWith(p => p.Documents1)等时 我有性能问题,想象2000个客户在内存列表中加载了所有这些众多的关系!

围绕文档的另一种方式 - >客户并不是一个问题,而是它的关系。

所以我尝试删除所有LoadWith,然后离开客户 - >地址关系。 现在,如果我去打开一个Document1,然后打开我的客户,当我序列化我的客户时,我得到一个对象处理异常。 serialize方法基本上抛出了这个异常。

序列化方法:

public static T CloneObjectGraph<T>(this T obj) where T : class 
        {
            var serializer = new DataContractSerializer(typeof(T), null, int.MaxValue, false, true, null);
            using (var ms = new System.IO.MemoryStream())
            {
                serializer.WriteObject(ms, obj);
                ms.Position = 0;
                return (T)serializer.ReadObject(ms);
            }
        }

方法我得到了客户:

public List<Customer> GetCustomers()
{
    using (MyDataContext db = new MyDataContext(MyDataContextManager.ConnectionString))
    {
        DataLoadOptions dlo = new DataLoadOptions();
        dlo.LoadWith<Customer>(p => p.Address);
        dlo.LoadWith<Customer>(p => p.Documents1);
        dlo.LoadWith<Customer>(p => p.Documents2);
        dlo.LoadWith<Customer>(p => p.Documents3);
        dlo.LoadWith<Customer>(p => p.Documents4);
        dlo.LoadWith<Customer>(p => p.Documents5);
        dlo.LoadWith<Customer>(p => p.Documents6);
        dlo.LoadWith<Customer>(p => p.Documents7);
        dlo.LoadWith<Customer>(p => p.Documents8);
        dlo.LoadWith<Customer>(p => p.Documents9);
        dlo.LoadWith<Customer>(p => p.Documents10);
        dlo.LoadWith<Customer>(p => p.Documents11);

        db.LoadOptions = dlo;

        return db.Customers.ToList();
    }
}

我想删除除Address关系之外的所有LoadWith。 我讨厌这个错误总是不能重现,但在某些情况下我找不到。

我可以猜测DataContractSerializer构造函数是否有变化,但我无法正确理解。

任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:1)

您的错误正在发生,因为您的克隆方法将尝试访问对象的所有子属性。当您具有LoadWith&lt;&gt;()语句时,这些子属性已从数据库中检索并在内存中可用。删除LoadWith&lt;&gt;()语句时,属性将尝试从数据库中延迟加载对象。因为您已经关闭了数据库连接,所以无法加载这些属性(并且您收到错误)。

解决方案取决于您尝试通过执行对象的深层复制来完成的任务;如果该深拷贝实际上确实需要具有子属性(DocumentsXX),那么您必须离开LoadWith&lt;&gt;()语句,或者您需要数据库连接在此过程中保持打开状态(两者之一,离开LoadWith&lt; ;&gt;()语句可能是更好的选择,因为它最小化了对数据库的访问,并最终使用相同数量的内存)。如果深层副本确实不需要包含这些属性,那么您需要将当前深度克隆过程替换为可以忽略这些属性(可以手动创建深度克隆或自定义序列化过程)。

相关问题