Почему LINQ 2 SQL при удалении контекста пытается получить дочерние отношения?

Я использую LINQ 2 SQL в одном из моих проектов, и у меня есть многочисленные отношения Клиент -> Документы1, Документы2, Документы3, Адрес, Счета и т. Д.....

При использовании LoadWith(p => p.Documents1)... и т.д. у меня возникают проблемы с производительностью, представьте себе 2000 клиентов со всеми этими многочисленными связями, загруженными в список в памяти!

С другой стороны, Document -> Customer - это не столько проблема, сколько отношения.

Поэтому я пытаюсь удалить все 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();
    }
}

Я хочу удалить все LoadWith, кроме отношения Адрес. Я ненавижу, когда эта ошибка не воспроизводится всегда, но в некоторых случаях я не мог найти.

Я мог бы угадать конструктор DataContractSerializer для изменения, но я не могу сделать это правильно.

Любая помощь приветствуется!

1 ответ

Решение

Произошла ваша ошибка, потому что ваш метод клонирования попытается получить доступ ко всем дочерним свойствам вашего объекта. Если у вас есть операторы LoadWith<>(), эти дочерние свойства уже извлекаются из базы данных и доступны в памяти. При удалении операторов LoadWith <>() свойства будут пытаться выполнить отложенную загрузку объектов из базы данных. Поскольку вы уже закрыли соединение с базой данных, эти свойства не могут быть загружены (и вы получите ошибку).

Решение зависит от того, чего вы пытаетесь достичь, выполняя глубокое копирование объектов; Если эта глубокая копия действительно должна иметь дочерние свойства (DocumentsXX), то вы должны либо оставить операторы LoadWith<>(), либо вам нужно, чтобы соединение с базой данных оставалось открытым во время процесса (из двух, оставляя LoadWith < Операторы>(), вероятно, являются лучшим вариантом, поскольку они сводят к минимуму доступ к БД и в конечном итоге используют тот же объем памяти). Если в глубокую копию действительно не нужно включать эти свойства, вам нужно заменить текущий процесс глубокого клонирования на, который может игнорировать эти свойства (будет работать либо созданный вручную глубокий клон, либо настроенный процесс сериализации).

Другие вопросы по тегам