实体框架核心中等效的 SQL RIGHT 函数
Posted
技术标签:
【中文标题】实体框架核心中等效的 SQL RIGHT 函数【英文标题】:SQL RIGHT function equivalent in Entity framework Core 【发布时间】:2019-02-12 06:17:08 【问题描述】:我正在处理一个 Net Core 项目,使用实体框架、mysql 数据库和 pomelo 框架。我需要执行此查询,以便将模型中属性的最后 X 个字符与模式进行比较:
_context.Cars
.Where(c => EF.Functions.Like(c.CarName.ToString().Right(5), pattern))
.ToList();
我想知道Entity framework Core中是否有任何等效的SQL RIGHT函数。
提前致谢
【问题讨论】:
Where(c => c.CarName.EndsWidth(pattern))
有效吗?如果没有,您收到的错误信息是什么?
我需要将最后 X 个字符与模式进行比较。示例:汽车名称 = “99114”。如果 X = 3 且模式 = "%11%",则该项目应包含在结果中。但是,如果 CarName="911"、X = 1 且模式 = "%11%",则该项目应从结果中排除。使用 EndsWith 会将“911”视为有效结果
【参考方案1】:
更新(EF Core 5.0+):
EF Core 5.0 在 DbFunctionAttribute
和 IsBuiltIn(bool)
fluent API 上引入了 IsBuiltIn
属性,因此不再需要提供翻译。最小映射与 EF Core 2.x 中的相同,只是
[DbFunction("RIGHT", "")]
替换为
[DbFunction("RIGHT", IsBuiltIn = true, IsNullable = true)]
EF Core 5 也允许Configuring nullability of user-defined function based on its arguments,但只能流畅地完成,因此您可以考虑使用显式映射而不是通用代码。例如
public static class MyDbFunctions
public static string Right(this string s, int length)
=> throw new InvalidOperationException();
public static void Register(ModelBuilder modelBuider)
var fb = modelBuilder.HasDbFunction(() => Right(default, default))
.HasName("RIGHT").IsBuiltIn(true).IsNullable(true);
fb.HasParameter("s").PropagatesNullability(true);
更新(EF Core 3.0+):
从 Ef Core 3.0 开始,空字符串模式被视为与 null
相同,即将默认模式添加到函数名称。这样,如果你想添加内置功能,你必须提供“翻译”(奇怪的决定)。
所以你需要添加
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
并修改代码如下
modelBuider.HasDbFunction(dbFunc).HasTranslation(args =>
SqlFunctionExpression.Create(dbFunc.Name, args, dbFunc.ReturnType, null));
原文:
由于目前既没有 CLR string
也没有 EF.Functions
方法称为 Right
,答案是 EF Core 目前不提供等效的 SQL RIGHT
函数。
幸运的是,EF Core 允许您使用引入的 EF Core 2.0 Database scalar function mapping 添加它。
例如,添加以下类:
using System;
using System.Linq;
namespace Microsoft.EntityFrameworkCore
public static class MyDbFunctions
[DbFunction("RIGHT", "")]
public static string Right(this string source, int length)
if (length < 0) throw new ArgumentOutOfRangeException(nameof(length));
if (source == null) return null;
if (length >= source.Length) return source;
return source.Substring(source.Length - length, length);
public static void Register(ModelBuilder modelBuider)
foreach (var dbFunc in typeof(MyDbFunctions).GetMethods().Where(m => Attribute.IsDefined(m, typeof(DbFunctionAttribute))))
modelBuider.HasDbFunction(dbFunc);
(稍后您可以根据需要添加更多类似的功能)。
然后从您的上下文 OnModelCreating
覆盖添加对 Register
的调用:
protected override void OnModelCreating(ModelBuilder modelBuilder)
// ...
MyDbFunctions.Register(modelBuilder);
// ...
你就完成了。现在您应该可以使用所需的:
_context.Cars
.Where(c => EF.Functions.Like(c.CarName.ToString().Right(5), pattern))
.ToList();
【讨论】:
这绝对是正确的答案。我对其进行了测试并按预期工作。谢谢!!! 这给了我以下错误:找不到列“dbo”或用户定义的函数或聚合“dbo.RIGHT”,或者名称不明确。我使用 DbFunction 的方式与您的代码示例相同。数据库 - SQL Server。 @VladyslavKolodka 是的,不幸的是,他们在 3.0 中改变了""
模式参数的含义,它不再被视为“无模式”。现在必须提供“翻译”。有时间我会更新解决方案,谢谢指出。
@IvanStoev 使用此代码修复:modelBuilder .HasDbFunction(typeof(CustomDbFunctions).GetMethod(nameof(Right))!) .HasSchema(null) .HasTranslation(args => SqlFunctionExpression.Create("RIGHT ", args, typeof(string), null));
@VladyslavKolodka 类似的东西。看起来不需要HasSchema(null)
,只需HasTranslation
。【参考方案2】:
使用以下内容:
_context.Cars.Where(w => DbFunctions.Right(w.CarName,5)==pattern).ToList();
【讨论】:
以上是关于实体框架核心中等效的 SQL RIGHT 函数的主要内容,如果未能解决你的问题,请参考以下文章