2010-08-19 4 views
0

У меня есть запрос LINQ to Entities (с использованием EF 4), который имеет довольно сложную фильтрацию на основе набора. Код компилируется нормально, но когда я пытаюсь запустить его, я получаю следующее сообщение об ошибке:Почему L2E задыхается, когда я пытаюсь использовать интерфейс в своем предложении Where?

Unable to create a constant value of type 'ITextEntity'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

Теперь код. У меня есть интерфейс, который выглядит следующим образом:

public interface ITextEntity 
{ 
    int ID { get; set; } 
    string TextValue { get; set; } 
    EntityCollection<Product> Products { get; set; } 
} 

Идея заключается в том, что эти «Текстовые Entities» представляют таблицы поиска хранящих свойства Product. Если продукты имеют цвет, все красные продукты будут содержать цвет лица с TextValue = «Red», и будет цвет лицо украшено этим интерфейсом:

public partial class Color : ITextEntity 
{ 
    //ID, TextValue, and Products implemented in EF-generated code 
} 

ITextEntities может иметь 1: N или N: N отношения назад к Product.

У меня есть вложенный набор (фактически List<IEnumerable<ITextEntity>>), который содержит наборы различных объектов, реализующих интерфейс ITextEntity. Я хочу использовать эти наборы для фильтрации последовательности Product s в полу-включительно. Вот код:

List<IEnumerable<ITextEntity>> InclusiveFilters; 
IQueryable<Product> Products; 

//...snip... 

Products = Products.Where(prod => 
    InclusiveFilters.All(filter => 
     filter.Any(iTextEnt => 
      iTextEnt.Product.Contains(prod) 
     ) 
    ) 
); 

Так что я пытаюсь сделать это:

  1. I have a set, Products, that I want to filter.
  2. For each of several types that implement ITextEntity , there's a set S of entities of that type.
  3. Each object O has a set O.P of products.
  4. For each Product prod in Products,
    for each set S,
    for at least one O in S,
    O.P must contain prod. If not, remove prod from Products.

Как вы можете видеть, что это довольно сложно.

У меня возникло ощущение, что это связано с тем, что LINQ не может работать с типом ITextEntity, а не с проблемой с моими заданиями. Однако сложность вышеизложенного затрудняет работу и трудно найти альтернативу, отличную от LINQ. Это будет довольно уродливо, если я не смогу использовать LINQ.

Я нашел an MSDN page и Stack Overflow thread, обсуждая подобные исключения, но ни одна из них не помогла. Another SO thread направляет палец на мое использование метода Contains, но из-за сложности здесь мне не очень повезло, чтобы заменить его на метод BuildOrExpression. Я сомневаюсь, что BuildOrExpression будет работать в любом случае, так как это поддерживается EF 4 и Contains.

Так что я скорее застрял здесь. Может ли кто-нибудь посоветовать?

EDIT: Этот вопрос был дан ответ в августе 2010 года, но я вернулся, чтобы очистить заголовок и описание.

+0

Проблема не 'Содержит'. Кажется, он находится в 'InclusiveFilters.All'. Это ваш код, я думаю, но вы его не показываете. –

+0

Простите, пожалуйста, уточните, что вы подразумеваете под «Это ваш код, я думаю, но вы его не показываете»? 'InclusiveFilters.All' - метод расширения IEnumerable . All'. –

+0

'InclusiveFilters' выглядел как тип вашего сообщения. Но теперь я вижу, что это капитализированный var. Я отвечу ниже. –

ответ

1

Вы неявно бросаете на ITextEntity. Но ITextEntity не является частью вашей модели данных сущности, поэтому EF не знает, как перевести ее члены в SQL. Contains поддерживается только с примитивными или сущностными типами. Кроме того, вы используете IEnumerable, что также предотвращает перевод на SQL; вам понадобится IQueryable для преобразования в SQL.

Итак, если вы удалите ссылку на интерфейс и IEnumerable, вы сможете выполнить запрос на сервере БД. В противном случае вам нужно перейти в L2O (с, например, AsEnumerable()).

+0

Итак, чтобы удалить интерфейс, вы, например, думаете, что-то вроде 'filter.Any (iTextEnt => iTextEnt.Product.Select (p => p.ID) .Contains (prod.ID))'? Это работает в L2O, но не в L2E. Я понимаю, что вы подразумеваете, подключая примитивный тип, а не интерфейс, но я не совсем уверен, как это сделать, чтобы L2E смог перевести. –

+1

Проблема 'InclusiveFilters'. Так как у него есть 'ITextEntity' в своем типе, он не может использоваться в L2E (в основном, конечно, не когда вы получаете эту ошибку). Все ссылки на этот тип, прямые или косвенные, должны быть удалены из запроса. –

+0

Обновление: Думаю, я понял это, хотя еще не проверял, что он обрабатывается сервером БД. Если это так, это будет выдающимся. Спасибо за вашу помощь. –