首页 > 解决方案 > 实体框架核心中等效的 SQL RIGHT 函数

问题描述

我正在处理一个 Net Core 项目,使用实体框架、mysql 数据库和 pomelo 框架。我需要执行此查询,以便将模型中属性的最后 X 个字符与模式进行比较:

_context.Cars
.Where(c => EF.Functions.Like(c.CarName.ToString().Right(5), pattern))
.ToList();

我想知道实体框架核心中是否有任何等效的 SQL RIGHT 函数。

提前致谢

标签: c#mysql.net-coreentity-framework-core

解决方案


更新(EF Core 5.0+):

EF Core 5.0 引入了IsBuiltIn属性 onDbFunctionAttributeIsBuiltIn(bool)fluent API,因此不再需要提供翻译。最小映射与 EF Core 2.x 中的相同,只是

[DbFunction("RIGHT", "")]

被替换为

[DbFunction("RIGHT", IsBuiltIn = true, IsNullable = true)]

EF Core 5 还允许根据其参数配置用户定义函数的可空性,但只能流畅地完成,因此您可以考虑使用显式映射而不是通用代码。例如


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));                    

原来的:

由于目前既没有 CLRstring也没有EF.Functions方法调用Right,答案是 EF Core 目前不提供等效的 SQLRIGHT函数。

幸运的是,EF Core 允许您使用 EF Core 2.0 引入的数据库标量函数映射来添加它。

例如,添加以下类:

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);
        }
    }
}

(稍后您可以根据需要添加更多类似的功能)。

Register然后从您的上下文OnModelCreating覆盖添加调用:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // ...
    MyDbFunctions.Register(modelBuilder);
    // ...
}

你完成了。现在您应该可以使用所需的:

_context.Cars
.Where(c => EF.Functions.Like(c.CarName.ToString().Right(5), pattern))
.ToList();

推荐阅读