0

我在我的一个项目中使用 LINQ 2 SQL,我有很多关系客户 - > Documents1、Documents2、Documents3、地址、发票等....

当使用 LoadWith(p => p.Documents1)...etc 时,我遇到了性能问题,想象一下 2000 个客户的所有这些大量关系都加载到内存中的 List 中!

Document -> Customer 的另一种方式与其说是关系,不如说是问题。

所以我尝试删除所有 LoadWith 并留下 Customer -> Address 关系。现在,如果我打开 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();
    }
}

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

我可以猜测 DataContractSerializer 构造函数进行更改,但我无法正确理解。

任何帮助表示赞赏!

4

1 回答 1

1

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

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

于 2010-11-04T16:19:24.407 回答