Why does L2E choke when I try to use an interface in my Where clause?

喜欢而已 提交于 2019-12-25 04:21:45

问题


I have a LINQ to Entities query (using EF 4) that has some pretty complicated set-based filtering going on. The code compiles just fine, but when I try to run it, I get the following error:

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

Now for the code. I have an interface that looks like this:

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

The idea is that these "Text Entities" represent lookup tables storing properties of Product. If Products have a color, all red Products will contain a Color entity with TextValue = "Red", and there will be a Color entity decorated with this interface:

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

ITextEntities may have 1:N or N:N relationships back to Product.

I have a nested collection (actually a List<IEnumerable<ITextEntity>>) which contains sets of different entities implementing the ITextEntity interface. I want to use these sets to filter a sequence of Products in a semi-inclusive fashion. Here's the code:

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

//...snip...

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

So what I'm trying to do is this:

  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.

As you can see, this is pretty complicated.

I have the feeling that this is caused by LINQ not being able to work with the ITextEntity type, rather than a problem with my set operations. However, the complexity of the above is making this difficult to work with, and difficult to find a non-LINQ alternative. It's going to get pretty ugly if I can't use LINQ.

I found an MSDN page and a Stack Overflow thread discussing similar exceptions, but neither was much help. Another SO thread aims a finger at my use of the Contains method, but because of the complexity here, I haven't had much luck trying to replace it with the BuildOrExpression method. I doubt BuildOrExpression will work anyway, since this is EF 4 and Contains is supposed to be supported.

So I'm rather stuck here. Can anyone advise?

EDIT: This question was answered in Aug 2010, but I've come back to clean up the title and description.


回答1:


You're implicitly casting to ITextEntity. But ITextEntity is not part of your entity data model, so the EF doesn't know how to translate its members into SQL. Contains is supported, but only with primitive or entity types. Also, you use IEnumerable, which also prevents translation to SQL; you need IQueryable to be convertable to SQL.

So if you remove the interface reference and IEnumerable, you should be able to execute the query on the DB server. Otherwise you have to go into L2O (with, e.g., AsEnumerable()).



来源:https://stackoverflow.com/questions/3523119/why-does-l2e-choke-when-i-try-to-use-an-interface-in-my-where-clause

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!