我正在开发一个使用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.AgeInYears
是int
。 EF不喜欢我给它int
而不是object
的事实。
那么,有什么方法可以做我想在这里做的事情?
答案 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类。