gpt4 book ai didi

c# - 如何使用 EntityFramework 6.2 将 DbFunctions/Sql 函数调用提取到可重用的扩展/方法中?

转载 作者:行者123 更新时间:2023-11-30 16:38:55 26 4
gpt4 key购买 nike

我有一个使用 C# 编写的应用程序在 ASP.NET MVC 5 框架之上。此外,我使用 EntityFramework 6.2 作为 ORM 来与我的数据进行交互。

我使用 Fluent LINQ 编写了以下连接语句

List<string> names = new List<string>{"", ....};
query = TopLevelQuery.Where(x => x.EndedAt.HasValue && x.StartedAt >= startedAt && x.EndedAt.Value <= endedAt)
.Join(UserService.QueryUniqueRecords(),
entry => entry.UserId,
rec => rec.UserId,
(entry, rec) => new { entry, rec })
.Where(result => result.entry.IsEqualDateOf(result.rec.DayOf)
&& names.Contains(result.rec.Name))
.Select(x => x.entry);

但是,我在运行时遇到以下错误

LINQ to Entities does not recognize the method 'IsEqualDateOf', and this method cannot be translated into a store expression.

这是我的 IsEqualDateOf扩展方法

public static class MyModelExtensions
{
public static DateTime GetLocalDate(this MyModel entry)
{
var local = DbFunctions.TruncateTime(SqlFunctions.DateAdd("ss", entry.UtcOffset, entry.StartedAt));

return local.Value;
}

public static bool IsEqualDateOf(this MyModel entry, DateTime dateOf)
{
bool isEqual = entry.GetLocalDate().Equals(dateOf.Date);

return isEqual;
}
}

但是,如果我将我的 LINQ 表达式转换为以下伪表达式,它会按预期工作

query = TopLevelQuery.Where(x => x.EndedAt.HasValue && x.StartedAt >= startedAt && x.EndedAt.Value <= endedAt)
.Join(UserService.QueryUniqueRecords(),
entry => entry.UserId,
rec => rec.UserId,
(entry, rec) => new { entry, rec })
.Where(result => DbFunctions.TruncateTime(SqlFunctions.DateAdd("ss", entry.UtcOffset, entry.StartedAt)) == result.rec.DayOf
&& names.Contains(result.rec.Name))
.Select(x => x.entry);

但是,我希望能够在我的项目中的多个地方重用相同的逻辑,这就是为什么我想将它提取到某种扩展或方法中。

如何,我可以提取 DbFunctionsSqlFunctionsAsEnumerable() 之前调用一个可重用的方法,该方法可以在 LINQ 中使用叫什么?

已更新

我还尝试通过将以下代码添加到 MyModel 来将逻辑提取到 lambda 表达式中类

public class MyModel
{
public DateTime StartedAt { get; set; }
public int UtcOffset { get; set; }
// ...

public Expression<Func<MyModel, bool>> IsDateOf(DateTime dayOf)
{
return p => p.StartedAt.AddSeconds(p.UtcOffset) == dayOf.Date;
}
}

然后我尝试这样消费它

query = TopLevelQuery.Where(x => x.EndedAt.HasValue && x.StartedAt >= startedAt && x.EndedAt.Value <= endedAt)
.Join(UserService.QueryUniqueRecords(),
entry => entry.UserId,
rec => rec.UserId,
(entry, rec) => new { entry, rec })
.Where(result => result.entry.IsDateOf(result.rec.DayOf)
&& names.Contains(result.rec.Name))
.Select(x => x.entry);

但是在尝试使用它时会抛出以下语法错误

Operator '&&' cannot be applied to operands of type 'Expression<Func<MyModel,bool>>' and bool.

此外,我尝试制作 IsDateOf表达式静态并这样调用它

query = TopLevelQuery.Where(x => x.EndedAt.HasValue && x.StartedAt >= startedAt && x.EndedAt.Value <= endedAt)
.Join(UserService.QueryUniqueRecords(),
entry => entry.UserId,
rec => rec.UserId,
(entry, rec) => new { entry, rec })
.Where(result => result.entry.Where(MyModel.IsDateOf(result.rec.DayOf))
&& names.Contains(result.rec.Name))
.Select(x => x.entry);

但这给了我以下语法错误

'MyMode' does not contain a definition for Where and the best extension method overload Queryable.Where<MyModel>IQueryable<MyModel>, Expression<Func<MyModel,
bool>>)
required a reciever of type IQueryable

最佳答案

从您的方法中删除参数并使表达式接受两个参数:

public static Expression<Func<MyModel, DateTime, bool>> IsDateOf 
= (MyModel p, DateTime d) => p.StartedAt.AddSeconds(p.UtcOffset) == d.Date;

请注意,我已将其设为静态字段,而不是方法。然后在您的 LINQ 表达式中,您需要调用它:

MyModel.IsDateOf(result.entry, result.rec.DayOf)

如果你不让它成为一个字段(或属性),你必须先调用方法来获取表达式;然后你需要调用表达式:

MyModel.IsDateOf()(result.entry, result.rec.DayOf)

在我看来,这看起来很奇怪。

关于c# - 如何使用 EntityFramework 6.2 将 DbFunctions/Sql 函数调用提取到可重用的扩展/方法中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53936854/

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