2009-11-08 3 views
5

У нас есть классыLinq субъектов - поиск в навигационных свойствах EntityCollection

public Invoice: EntityObject 
{ 
    public EntityCollection<InvoicePosition> Positions { get {...}; set{...}; } 
    ... 
} 

public InvoicePosition: EntityObject 
{ 
    public string GroupName { get {...}; set{...}; } 
} 

Мы приведены IQueryable<Invoice>, нам не даны IQueryable<InvoicePosition>. Как мне найти счета, у которых есть позиции, где GroupName - «Топливо»?

IQueryable<Invoice> invoices = InvoiceRepository.List(); 
IQueryable<Invoice> invoicesThatHaveFuelPositions = 
    from i in invoices 
    where ? 
    select i 

EntityFramework должен иметь возможность перевести его в соответствующий sql-запрос.

EDIT

Как писал Марк Seemann, я могу использовать:

IQueryable<Invoice> invoices = InvoiceRepository.List().Include("Positions").Include("OtherInclude"); 
IQueryable<Invoice> invoicesThatHaveFuelPositions = 
    from i in invoices 
    from p in i.Positions 
    where p.GroupName = 'Fuel' 
    select i; 

Существует проблема. Когда я использую эту фильтрацию, я теряю «OtherInclude». Я думаю, что это не правильный способ фильтрации при использовании EF. Я должен будет изменить его на:

IQueryable<Invoice> invoices = InvoiceRepository.List().Include("Positions").Include("OtherInclude"); 
IQueryable<Invoice> invoicesThatHaveFuelPositions = invoices.Where(???); 

Но что я должен писать в Где?

EDIT

Изменено Включить ("Position"), чтобы включить ("позиции").

EDIT

Алекс Джеймс дал ссылку на кончике (http://blogs.msdn.com/alexj/archive/2009/06/02/tip-22-how-to-make-include-really-include.aspx), что наводит на мысль:

IQueryable<Invoice> invoicesThatHaveFuelPositions = 
    from i in invoices 
    where i.Positions.Any(p => p.GroupName == 'Fuel') 
    select i; 

Это похоже на работу и не влияет на EF включает в себя.

ответ

5

Опираясь на Marks ответ. Если вы сделаете это:

var q = from i in invoices.Include("something") 
     from p in i.Positions 
     where p.GroupName == "Fuel" 
     select i; 

включаемом теряется (см this tip), потому что EF теряет все включает в себя, если меняется форма запроса, например, если вы неявно включается как в запросе SelectMany, иначе это от ,

Обходной путь заключается в том, чтобы написать ваш запрос, а затем в конце применить Include.

Что-то вроде этого:

var q = ((from i in invoices 
     from p in i.Positions 
     where p.GroupName == "Fuel" 
     select i) as ObjectQuery<Invoice>).Include("something"); 

Если вы сделаете это в Entity Framework на самом деле включаемый.

Надеется, что это помогает

Alex

+0

Спасибо за этот отзыв. Добавление Include в конце является проблематичным, потому что я использую шаблон репозитория, а Includes - сначала. Среднее решение (с помощью Any()) подходит мне. – LukLed

2

Нечто подобное должно работать:

var q = from i in invoices 
     from p in i.Positions 
     where p.GroupName == "Fuel" 
     select i; 

Однако, что использует навигационное свойство Positions, который по умолчанию не загружается (Entity Framework использует явную загрузку). Это будет, однако, работа, если переменная invoices была создана так:

var invoices = from i in myObjectContext.Invoices.Include("Positions") 
       select i; 
+0

Если скомпилировано, может быть, это будет работать :) – LukLed

+0

Invoice.Positions является EntityCollection. Он не имеет свойства GroupName. В нем есть список InvoicePosition. – LukLed

+0

Извините, я неправильно прочитал код в вопросе. Я только что обновил ответ. –

Смежные вопросы