Entity framework 实体框架通用于何处

Entity framework 实体框架通用于何处,entity-framework,entity-framework-4,notsupportedexception,Entity Framework,Entity Framework 4,Notsupportedexception,我有两个具有共同属性的实体。我需要使用公共属性在查询中应用一些where。所以我决定这样做: public interface IContract { string Name{get;set;} } public class Entity1 : IContract { public string Name{get;set;} } public class Entity2 : IContract { public string Name{get;set;} } pub

我有两个具有共同属性的实体。我需要使用公共属性在查询中应用一些where。所以我决定这样做:

public interface IContract
{
    string Name{get;set;}
}

public class Entity1 : IContract
{
    public string Name{get;set;}
}

public class Entity2 : IContract
{
    public string Name{get;set;}
}

public class Repository
{
    public IQueryable<T> Filter<T>(IQueryable<T> query, Request request) where T : IContract
    {
        return query.Where(x => x.Name== request.Name);
    }
    public IQueryable<Entity1> GetEntitity1()
    {
        return Filter(entities.Entity1, new Request { Name = "X" };
    }

    public IQueryable<Entity2> GetEntitity2()
    {
        return Filter(entities.Entity2, new Request { Name = "X" };
    }
}
公共接口IContract
{
字符串名称{get;set;}
}
公共类实体1:IContract
{
公共字符串名称{get;set;}
}
公共类实体2:IContract
{
公共字符串名称{get;set;}
}
公共类存储库
{
公共IQueryable筛选器(IQueryable查询、请求),其中T:IContract
{
返回query.Where(x=>x.Name==request.Name);
}
公共IQueryable getEntity1()
{
返回筛选器(entities.Entity1,新请求{Name=“X”};
}
公共IQueryable getEntity2()
{
返回筛选器(entities.Entity2,新请求{Name=“X”};
}
}
问题是使用这种方式,在apply.ToList()之后,我收到: NotSupportedException.LINQ to Entities仅支持强制转换EDM基元或枚举类型

我有办法修复它,还是需要使用ObjectQuery的Where(字符串)


谢谢

问题是,T的类型约束是一个接口。 filter方法的结果基本上是这样的查询

entities.Entity1.Where(p => ((IContract)p).Name == request.Name);
entities.Entity1.Where(p => p.Name == request.Name);
此((IContract)p)强制转换无法转换为sql语句。由于此强制转换在您的情况下或多或少是无用的,因此可以将其从查询表达式中删除。最好的方法是使用ExpressionVisitor

public IQueryable<T> Filter<T>(IQueryable<T> query, Request request) where T : IContract
{
    var result =  query.Where(x => x.Name == request.Name);
    result = RemoveContract<T, IContract>(result);
    return result;
}

public IQueryable<T> RemoveContract<T, TContract>(IQueryable<T> query) where T : TContract
{
    var exp = query.Expression;
    exp = new RemoveConvertExpressionVisitor<TContract>().Visit(exp);
    return query.Provider.CreateQuery<T>(exp);
}

private class RemoveConvertExpressionVisitor<TContract> : ExpressionVisitor{
    public override Expression Visit(Expression node)
    {
        var unary = node as UnaryExpression;
        if (unary != null && unary.Type == typeof(TContract)) {
            return unary.Operand;
        }
        return base.Visit(node);
    }
}