使用Entity Framework Core (2.1)调用标量函数的最佳实践

13
我经常需要从我的Web应用程序(ASP.NET Core / EF Core)调用在SQL Server上定义的标量函数。由于这些函数只是简单的辅助函数,我也使用了很多,因此我使用通用模式来调用这些标量函数 - 借助EF Core 2.1提供的新查询类型。 由于我对EF Core相对较新,所以我的问题是,这种模式是否会导致问题和/或是否有更好的解决方案或最佳实践来调用标量函数。该解决方案有效,到目前为止我还没有发现任何问题,但例如,我想知道是否使用相同的查询类型来调用不同的函数可能会导致意外值或由于EF Core中的缓存/跟踪行为等而导致奇怪的行为 - 这更像是一种直觉感觉。
因此,这里是模式: 我不是为每个单独的标量函数定义不同的实体类型,而是定义一个通用类型:
public class PrimitiveDto<T>
{
    public T Value { get; set; }
}

在我的上下文类中,我为每个我想要使用的标量函数返回类型注册这些类型 - 因此,对于所有返回“int”的标量函数,上下文类将有一个额外的条目,如下所示:
public virtual DbQuery<PrimitiveDto<int>> BasicIntDto { get; set; }

对于 EF Core >= 3 版本,它是:

public virtual DbSet<PrimitiveDto<int>> BasicIntDto { get; set; }

在应用程序的每个需要调用返回'int'的标量函数的部分,我都只是使用以下相同的模式:

context.BasicIntDto.FromSql("SELECT <FUNCTION> AS Value")

通过使用这种模式,我可以以相同的方式调用任意数量的函数,而无需定义其他类型或扩展上下文类。
请告诉我是否会通过这种模式陷入陷阱。非常感谢。

1
我认为它没有什么大问题,但你可能可以对其进行重构,这样在每次调用时就不必提供整个查询。例如,为上下文创建一个属性,在每个函数/存储过程中返回一个BasicDto<int>,接受所需的任何参数。 - Bradley Uffner
1
为什么不使用数据库标量函数映射呢?是的,它需要扩展上下文类,但不需要额外的类型,并提供了可重用性、智能感知支持和编译时检查,就像常规的LINQ和CLR方法一样。 - Ivan Stoev
1
感谢Ivan Stoev的提示 - 我必须承认我之前不知道这个功能。但是事实证明,你不能直接通过这个特性调用标量函数 - 你必须从一个实体类型开始,然后可以在查询中使用这些方法存根(即context.ENTITY.where(x => x.METHODSTUB()) ...)。然而,他们似乎正在解决这个问题(请参见https://github.com/aspnet/EntityFrameworkCore/issues/9810)。所以再次感谢你指出这一点。 - Grimm
你可以在结果上使用 Enumerable.Single 方法。 - Mark G
1
看起来DbQuery在EF Core 3中已被弃用,所以应该使用DbSet<PrimitiveDto<int>> - Endy Tjahjono
显示剩余5条评论
1个回答

1
很不幸,这个功能似乎已被搁置:https://github.com/aspnet/EntityFrameworkCore/issues/9810 一种选择是将函数调用包装在一个静态类中,使用一个永远不为空的小表格:
public static class DbFunctions
{
   public static decimal MyFunctionABC(int param1, int param2)
   {
       using (var db = new MyDbContext())
       {
        return db.table.Take(1).Select(t => MyDbContext.MyFunctionABC(x, y)).Single();
       }
    }
 }

然后你可以调用 DbFunctions.MyFunctionABC(x,y);

我喜欢这种方法,并在另一种解决方案中使用了它:https://dev59.com/RbHma4cB1Zd3GeqPRM5l#68902584 - Extragorey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接