首先映射数据库函数,再在LINQ中调用。1. 标量函数用[DbFunction]标记静态方法,EF Core生成SQL调用;2. 表值函数通过FromSqlRaw查询并映射到实体类;3. 推荐使用HasDbFunction在OnModelCreating中显式配置函数名和模式。注意函数需为static、返回类型匹配、方法体抛出NotSupportedException,且仅用于可翻译的查询上下文。

在C#中使用EF Core查询时,如果需要调用数据库中的自定义函数(如标量函数或表值函数),可以通过映射函数到模型并使用FromSqlRaw或HasDbFunction来实现。下面介绍两种主要方式:映射数据库函数和在LINQ中调用。
1. 映射数据库标量函数(Scalar Function)
假设你在SQL Server中有一个标量函数:
CREATE FUNCTION dbo.CalculateDiscount(@price DECIMAL(18,2), @rate DECIMAL(3,2)) RETURNS DECIMAL(18,2) AS BEGIN RETURN @price * (1 - @rate) END你可以在EF Core的DbContext中映射这个函数:
步骤:
- 在
DbContext中定义一个静态方法,并用[DbFunction]标记 - 确保该方法名与数据库函数名一致(或指定名称)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 可选:显式配置函数名(如果方法名不同)
modelBuilder.HasDbFunction(typeof(AppDbContext).GetMethod(nameof(CalculateDiscount)));
} }
然后在LINQ查询中使用:
var result = context.Products .Select(p => new { Name = p.Name, DiscountedPrice = CalculateDiscount(p.Price, 0.1m) }) .ToList();EF Core会生成类似SELECT Name, dbo.CalculateDiscount(Price, 0.1) AS DiscountedPrice FROM Products的SQL。
2. 调用表值函数(Table-Valued Function)
如果函数返回的是结果集(例如TVF),可以使用FromSqlRaw直接调用。
例如SQL Server中的TVF:
CREATE FUNCTION dbo.GetProductsByCategory(@categoryId INT) RETURNS TABLE AS RETURN ( SELECT Id, Name, Price FROM Products WHERE CategoryId = @categoryId )你需要定义一个只读实体类来接收结果:
public class ProductSummary { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } }然后通过FromSqlRaw调用:
3. 使用 HasDbFunction 显式配置(推荐方式)
除了属性方式,也可以在OnModelCreating中更灵活地配置:
这种方式便于集中管理,也支持重命名。
注意事项
- 标量函数必须是
static且返回类型匹配 - 方法体应抛出
NotSupportedException,防止被意外调用 - 仅支持可翻译成SQL的函数调用,不能用于内存查询(如
.Where()之后) - 注意数据库大小写敏感性,尤其是在非SQL Server环境下
基本上就这些。根据你的数据库函数类型选择合适的方式即可。










