如何编写EF.Functions扩展方法?

时间:2017-09-14 07:10:53

标签: sql-server linq entity-framework-core asp.net-core-mvc-2.0

我看到EF Core 2有EF.Functions属性EF Core 2.0 Announcement which can be used by EF Core or providers to define methods that map to database functions or operators so that those can be invoked in LINQ queries。它包括发送到数据库的LIKE方法。

但是我需要一个不同的方法,包括的SOUNDEX()。如何编写这样一种方法,将函数以DbFunction属性在EF6中的方式传递给数据库?或者我需要等待MS实施它?基本上,我需要生成像

这样的东西
SELECT * FROM Customer WHERE SOUNDEX(lastname) = SOUNDEX(@param)

2 个答案:

答案 0 :(得分:7)

EF.Functions添加新的标量方法很简单 - 只需在DbFunctions类上定义扩展方法即可。但是,提供SQL转换很困难,需要深入研究EFC内部。

然而,EFC 2.0还引入了一种更简单的方法,在 EF Core 2.0 文档主题中的新功能的Database scalar function mapping部分中进行了解释。

根据这一点,最简单的方法是在DbContext派生类中添加静态方法,并用DbFunction属性标记它。 E.g。

public class MyDbContext : DbContext
{
    // ...

    [DbFunction("SOUNDEX")]
    public static string Soundex(string s) => throw new Exception();
}

并使用以下内容:

string param = ...;
MyDbContext db = ...;
var query = db.Customers
    .Where(e => MyDbContext.Soundex(e.LastName) == MyDbContext.Soundex(param));

您可以在不同的类中声明此类静态方法,但是您需要使用HasDbFunction流畅的API手动注册它们。

答案 1 :(得分:1)

根据https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#udf-empty-string

,EFC 3.0对该过程进行了一些更改

在部分上下文类中添加CHARINDEX的示例:

public partial class MyDbContext
{
    [DbFunction("CHARINDEX")]
    public static int? CharIndex(string toSearch, string target) => throw new Exception();

    partial void OnModelCreatingPartial(
        ModelBuilder modelBuilder)
    {
        modelBuilder
            .HasDbFunction(typeof(MyDbContext).GetMethod(nameof(CharIndex)))
            .HasTranslation(
                args =>
                    SqlFunctionExpression.Create("CHARINDEX", args, typeof(int?), null));
    }
}