问题
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 Product
s 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:
- I have a set, Products, that I want to filter.
- For each of several types that implement
ITextEntity
, there's a set S of entities of that type.- Each object O has a set O.P of products.
- 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