Entity-Framework, как проецировать в список - PullRequest
2 голосов
/ 21 сентября 2009

Я использовал linq2sql в нескольких проектах, но я решил, что пришло время попробовать EF, так как он должен быть более мощным и лучшим. Есть несколько вещей, которые действительно раздражают. Один из них проецирует результат в список, это хорошо работает в l2sql, но не в EF.

public class bo.Transaction
{
  public long Id { get; set; }
  public List<bo.Line> Lines { get; set; }
}

public class bo.Line
{
  public int RowNo { get; set; }
  public string Descripton{ get; set; }
  public double Amount{ get; set; }
}

return from t in Db.Transaction.Include("Lines")
       select new bo.Transaction {
         Id = t.Id,
         Lines = t.Lines.OrderBy(l => l.RowNo).ToList(),
       };

Однако вызов ToList () завершается неудачно с сообщением " System.NotSupportedException: LINQ to Entities не распознает метод метода List [bo.Line] ToListLine", и этот метод нельзя преобразовать в хранилище. выражение .. ».

Есть ли способ обойти это? Или мне просто нужно использовать ienumerable вместо списков?

Ответы [ 3 ]

2 голосов
/ 21 сентября 2009
return (from t in Db.Transaction.Include("Lines")
       select new bo.Transaction {
         Id = t.Id,
         Lines = t.Lines.OrderBy(l => l.RowNo),
       }).ToList();

Запрос Linq просто не поддерживает список, поэтому мы выполняем это в результате перечисления. Тем не менее, это заставляет Запрос исполняться прямо в этот момент. Возвращение IEnumerable задержит выполнение запроса немного дольше. (В основном до того момента, когда вы собираетесь получить доступ к данным.)

0 голосов
/ 21 сентября 2009

То, что написал Мастерская Алекса, верно, но позвольте мне объяснить теорию, стоящую за этим:
как вы, вероятно, знаете, когда вы пишете запрос LINQ-to-Entities, вы пишете что-то, что будет выполнено для вашей базы данных. Для того чтобы это было сделано эффективным способом, вместо выборки каждой сущности, проверки ее по заданным критериям, сортировки результата и таких операций, запрос будет переведен в SQL и запущен для вашей базы данных.
Однако тот факт, что любой допустимый C # принят для вашего запроса, не означает, что весь код, который вы можете написать, имеет перевод на SQL. Известные примеры кода без перевода - это запрос, смешивающий доступ к данным и отражение в ваших классах сущностей, или - как и в вашем случае - код с использованием особых типов данных .NET. Такие запросы обычно могут быть выполнены в два этапа, один из которых работает с базой данных, а другой - с объектами в оперативной памяти. Хотя это, вероятно, не будет столь же эффективным и чистым, как вы хотели бы, поскольку лично мне не нравятся хранимые процедуры, я все же нахожу это намного лучше, чем большинство других подходов, которые вы можете использовать, при условии, что ваши ограничения позволяют вам сделать выбор.

Edit:
сценарий действительно может быть легко обработан при выполнении части запроса на БД и части в памяти следующим образом:


Db.Transaction.Include("Lines").Select(t => new bo.Transaction { t.Id, Lines = t.Lines.OrderBy(l => l.RowNo) }).AsEnumerable().Select(t => new bo.Transacton { t.Id, Lines = t.Lines.ToList()});

Вызов AsEnumerable помогает убедиться, что второй Select запускается для набора объектов, уже извлеченных из БД, и, следовательно, больше не возникает проблема перевода ToList в SQL.

0 голосов
/ 21 сентября 2009

Это удар в темноте, но есть ли в вашем проекте ссылка на System.Core dll? Без этой ссылки метод расширения .ToList () будет недоступен.

Кроме того, как отмечает Семинар Алекс, ваш вызов .ToList () находится не в том месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...