gpt4 book ai didi

c# - linq2entities 的 IQueryable 扩展方法

转载 作者:太空狗 更新时间:2023-10-29 21:29:07 24 4
gpt4 key购买 nike

我正在尝试实现一个可与 linq2entities 一起使用的扩展方法。我最初假设如果我的扩展方法接受并返回一个 IQueryable,并且只要我的表达式只使用支持的方法,那么它就可以正常工作。我遇到了很多麻烦,所以作为最后的手段,我复制了一个我知道可以工作的现有 .NET 扩展方法 (FirstOrDefault) 并简单地重命名它。它似乎会根据方法返回的表达式而不是方法本身的名称来评估“无法转换为存储表达式”验证。

var prs = db.People.Where(p => p.PersonKey == 15).Select(p =>
new
{
id = p.PersonKey,
name1 = p.PersonHistories.AsQueryable().AsOf().Name
}
).ToList();

我的扩展方法,它只是我重命名的 FirstOrDefault 的一个副本:

public static TSource AsOf<TSource>(this IQueryable<TSource> source)
{
return source.Provider.Execute<TSource>(Expression.Call(null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression }));
}

错误:

LINQ to Entities does not recognize the method 
'Models.PersonHistory AsOf[PersonHistory](System.Linq.IQueryable`1[Models.PersonHistory])'
method, and this method cannot be translated into a store expression.

如何实现 Linq2Entities 支持的 IQueryable 扩展方法?

我真正想要 AsOf(source, DateTime asOf) 做的事情是 source.FirstOrDefault<IHistory>(s => s.EndDate > asOf && asOf >= s.StartDate ) , 但我不确定如何完成此操作以便 linq2entities 支持它。

LINQKIT:这是我使用 linqkit 得出的结果,我希望能以某种方式将其纳入更可重用的东西中:

Expression<Func<PersonHistory, bool>> IsCurrent = (p) => p.Ends > DateTime.Now && p.Starts <= DateTime.Now;
var query = db.PersonHistories.Where(IsCurrent);
  1. 有一个更全局声明的表达式,而不是局部的变量。
  2. 添加 DateTime asOf 参数,而不是对 .Now 进行硬编码。
  3. 如果可能的话,把它改编成一个扩展方法(这种与#1 相同,只是扩展方法是理想的。

最佳答案

这应该可以在不扩展您的查询提供程序的情况下工作。它基本上将其分解为您的 IsCurrent 函数正在执行的操作。

public static class IQueryableExtensions
{
public static IQueryable<T> IsCurrent<T>(this IQueryable<T> query,
Expression<Func<T, DateTime?>> expressionEnd,
Expression<Func<T, DateTime?>> expressionStart,
DateTime asOf) where T : class
{
// Lambdas being sent in
ParameterExpression paramEnd = expressionEnd.Parameters.Single();
ParameterExpression paramStart = expressionStart.Parameters.Single();

// GT Comparison
BinaryExpression expressionGT = ExpressionGT(expressionEnd.Body, asOf);

// LT Comparison
BinaryExpression expressionLT = ExpressionLE(expressionStart.Body, asOf);

query = query.Where(Expression.Lambda<Func<T, bool>>(expressionGT, paramEnd))
.Where(Expression.Lambda<Func<T, bool>>(expressionLT, paramStart));

return query;
}

private static BinaryExpression ExpressionLE(Expression body, DateTime value)
{
return Expression.LessThanOrEqual(body, Expression.Constant(value, typeof(DateTime)));
}

private static BinaryExpression ExpressionGT(Expression body, DateTime value)
{
return Expression.GreaterThan(body, Expression.Constant(value, typeof(DateTime)));
}
}

并使用它

var query = db.PersonHistories.IsCurrent( p => p.Ends, 
p => p.Starts,
DateTime.Now );

关于c# - linq2entities 的 IQueryable 扩展方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10826275/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com