Левое внешнее соединение в Linq To Entities (сущность или сложный тип не могут быть созданы в запросе LINQ to Entities.)

У меня есть два класса, которые сопоставляют две таблицы моей базы данных:

public class Product
{
    public int Id { get; set; }
    public string Token { get; set; }
    public string Name { get; set; }
    public decimal Value { get; set; }
}

public class Ticket
{
    public int Id { get; set; }
    public string SerialNumber { get; set; }
    public string ProductToken { get; set; }
    public Product Product { get; set; }
}

По некоторым причинам домена продукт и билет логически связаны, другими словами, они не связаны в отношениях с базой данных, которые могут быть сопоставлены EF, они будут связаны в моем приложении с запросом linq, который «должен» быть переведен в Внешнее левое соединение SQL. Отсюда я сделал следующий запрос:

IQueryble<Ticket> query = from ts in context.Tickets
                          join ps in context.Products 
                               on ts.ProductToken equals ps.Token into p
                          select new Ticket
                          {
                              Id = t.Id,  
                              SerialNumber = t.SerialNumber,
                              ProductToken = t.ProductToken,
                  Goal -----> Product = p.FirstOrDefault()
                          };

Запрос сохраняется как IQueryble, потому что после этого запрос продолжает уточняться с помощью фильтра.

Проблема в том, что я запускаю следующий код:

var tickets = query.OrderBy(t => t.SerialNumber).ToList();

Получила следующую ошибку:

"The entity or complex type 'Model.Ticket' cannot be constructed in a LINQ to Entities query."

Итак, как я могу достичь своей цели?


person Vinicius Ottoni    schedule 17.04.2012    source источник


Ответы (1)


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

public class myTicket
{
    public int Id { get; set; }
    public string SerialNumber { get; set; }
    public string ProductToken { get; set; }
    public Product Product { get; set; }
}

а потом:

IQueryble<myTicket> query = from ts in context.Tickets
                          join ps in context.Products 
                               on t.ProductToken equals p.Token into p
                          select new myTicket
                          {
                              Id = t.Id,  
                              SerialNumber = t.SerialNumber,
                              ProductToken = t.ProductToken,
                              Product = p.FirstOrDefault()
                          };

Также вам необходимо использовать DefaultIfEmpty () для левого внешнего соединения.

person Habib    schedule 17.04.2012
comment
Хорошая работа, просто обратите внимание, что вы пропустили заказ по серийному номеру :) - person mattytommo; 17.04.2012
comment
Я не понимал, почему мне нужно создать новый класс, идентичный классу POCO, и если вы создаете new myTicket в возврате select, почему IQueryble ‹Ticket› сохраняет то же самое (Ticket), он будет работать, нужны некоторые В ролях? - person Vinicius Ottoni; 17.04.2012
comment
@ViniciusOttoni, IQueryable ‹ticket› была опечаткой, там должен быть myTicket. Причина, по которой вы не можете проецировать сопоставленный объект, заключается в том, что объект представляет таблицу базы данных. Используя проект, вы выбираете часть этой таблицы (некоторые столбцы), которая является недопустимым состоянием для данных - person Habib; 17.04.2012
comment
Нет возможности выбрать часть данных и продолжать выполнять другие запросы с основным запросом? - person Vinicius Ottoni; 17.04.2012
comment
@ViniciusOttoni, в вашем случае я не знаю, есть ли, но я бы хотел знать - person Habib; 17.04.2012