订单在EF linq中实体无法处理我正在抛出的善意。

时间:2011-07-29 16:43:31

标签: c# linq entity-framework linq-to-entities

我正在开发一个使用Entity Framework 3.5和SQL数据库的应用程序。该应用程序根据从用户界面传递的一些搜索条件搜索对象图。为了处理搜索功能,我正在使用具有以下界面的查询构建器:

public interface IQueryBuilder
{
    IQueryable<SomeClass> BuildQuery(Criteria criteria);    
}

条件对象包含查询构建器用于过滤搜索结果的多个属性。它还带有一个属性,指示如何对结果进行排序,称为“OrderBy”。以下是标准对象的示例:

public class Criteria
{
    //some filter properties...

    public Expression<Func<SomeClass, object>> OrderBy { get; set; }
}

因此,在构建初始查询之后,查询构建器使用以下命令对查询进行排序:

var sortedQuery = query.OrderBy(criteria.OrderBy);

当我通过字符串属性(OrderBy = x => something.LastName)进行排序时,这在单元测试和集成测试(实际上它击中EF)中完美无缺。但是,当我运行按非字符串属性(OrderBy = x => something.AgeInYears)排序的集成测试时,EF抛出以下异常:

System.NotSupportedException: Unable to cast the type 'System.Int32' to type 'System.Object'. LINQ to Entities only supports casting Entity Data Model primitive types.

在这种情况下,something.AgeInYearsint。 EF不喜欢我给它int而不是object的事实。

那么,有什么方法可以做我想在这里做的事情?

2 个答案:

答案 0 :(得分:3)

我猜你不想(有充分理由)让你的标准类像

public class Criteria<T, U>
{
    //some filter properties...

    public Expression<Func<T, U>> OrderBy { get; set; }
}

应该有用......所以这里有几个选择:

public class Criteria<T>
{
    //some filter properties...

    public Expression OrderBy { get; set; }


    public void CreateOrdering<U>(Expression<Func<T, U>> value)
    {
        OrderBy = value;
    }
}

但由于OrderBy不再是通用类型,因此您需要更改应用它的代码:

      var orderBy = Expression.Call(
            typeof(Queryable),
            "OrderBy",
            new Type[] { query.ElementType, query.ElementType },
            query.Expression,
            criteria.OrderBy);

      var sortedQuery = query.Provider.CreateQuery<T>(orderBy

或者,您可以在随后应用排序的代码中处理此问题:

而不是

var sortedQuery = query.OrderBy(criteria.OrderBy);

做类似的事情(没有测试过这个,但应该基本上是这样的)(更新:这个没有假设您正在使用泛型)。

// grab the property expression out of your ordering statement
var expressionProperty = criteria.OrderBy.Body is UnaryExpression ? (MemberExpression)((UnaryExpression)criteria.OrderBy.Body).Operand : (MemberExpression)criteria.OrderBy.Body;

// recreate the lambda as Expression<Func<T,U>> where T is the queryable element type and U 
// is the actual type of the property, not an object

var orderBy = Expression.Lambda(expressionProperty, criteria.OrderBy.Parameters.Single());

// apply new lambda instead
var sortedQuery = query.OrderBy(orderBy);

答案 1 :(得分:0)

检查可以帮助进行LINQ安全转换的methods on the SqlFunctions类。