LINQ to SQL использовать запрос после DataContext Dispose - PullRequest
2 голосов
/ 14 марта 2012

Я пишу DLL для одного проекта, я только начал использовать LINQ to SQL и после перемещения всех методов в эту новую DLL. Я обнаружил, что не могу получить доступ к DataContext, потому что он был удален, я понимаю, почему, но я не уверен, как я могу обработать результаты запроса для моего основного метода проекта так:

Мой метод в DLL

 public static IEnumerable<Problem> GetProblemsNewest(int howMuch)
        {
            using (ProblemClassesDataContext context = new ProblemClassesDataContext())
            {
                var problems = (from p in context.Problems orderby p.DateTimeCreated select p).Take(howMuch);

                return problems;
            }
        }

Называя это:

IEnumerable<Problem> problems = ProblemsManipulation.GetProblemsNewest(10);
//Error can't acess it because it was disposed..

Это только первый метод, у меня есть более крупные, поэтому мне действительно нужен способ сделать это. Должен быть способ использовать LINQ to SQL в DLL? Я знаю, что могу сделать что-то вроде .ToList или .ToArray, но тогда я не смогу напрямую получить доступ к свойствам строки, и мне пришлось бы ссылаться на это как на проблему [0], проблему [1] и т. Д., Что еще более беспорядочно чем иметь тон кода в основном проекте.

Ответы [ 6 ]

7 голосов
/ 14 марта 2012

После того, как вы вышли за пределы оператора using, контекст автоматически удаляется, поэтому, когда IEnumerable фактически перечисляется, контекст уже удаляется.

Поэтому вам нужно сказать Linq, что он должен идти вперед и действительно получатьзначения из БД в то время как вы внутри вашего using заявления.Вы можете сделать это через ToList() или ToArray (или другие).

См. Обновленный код:

public static IList<Problem> GetProblemsNewest(int howMuch)
{
    using (ProblemClassesDataContext context = new ProblemClassesDataContext())
    {
        var problems = (from p in context.Problems orderby p.DateTimeCreated select p).Take(howMuch);

        return problems.ToList();
    }
}
4 голосов
/ 14 марта 2012

Измените это:

return problems;

на это:

return problems.ToList();

Объяснение :

ToList () будет перебирать результатыи вытащить их всех в память.Поскольку это происходит внутри оператора using, все в порядке.И поскольку он создает список, ваши значения будут возвращены.

Вы можете сделать это другими способами.Основная идея состоит в том, чтобы на самом деле получить результаты до закрытия оператора using.

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

1 голос
/ 14 марта 2012

В настоящее время вы возвращаете запрос, и когда вы хотите его использовать, поскольку соединение с базой данных было закрыто до вашего использования, вы получите исключение, просто выполните:

return problems.AsEnumerable()

Это из-за отложенного исполнения в стиле linq. Фактически, ваш problems объект - это просто запрос, и вы должны преобразовать его в объекты, чтобы использовать его где-то еще.

1 голос
/ 14 марта 2012

Вы должны завершить запрос внутри предложения using, т. Е. Использовать ToList () или First () или Count () и т. Д. ...

1 голос
/ 14 марта 2012

Вы можете справиться с этим, выполнив .ToList () в IEnumerable перед выходом из блока using. Это позволит получить записи и заполнить список. В зависимости от вашего сценария это может быть не оптимальным с точки зрения производительности (вы теряете возможность ленивого поиска и дополнительной фильтрации запроса)

0 голосов
/ 14 марта 2012

Возможно, вы не захотите использовать контекст в использовании; проблема в том, что вы не сможете использовать свойства навигации позже, потому что у вас будет та же проблема «удаления объекта», когда он попытается загрузить связанные данные. Что вам нужно сделать, это позволить контексту жить и возвращать результаты напрямую. Или, когда вы возвращаете результаты, позвоните ToList(), а затем запросите все связанные данные.

...