如何在Entity Framework Core 9中映射多语句表值函数?
EF Core 映射多语句表值函数(返回非实际存在的表)
问题背景
官方文档未覆盖多语句表值函数的配置场景,现需实现EF Core对这类函数的映射——函数返回的表并非数据库中实际存在的物理表。
测试用SQL多语句表值函数
CREATE FUNCTION [dbo].[fn_multi_statement_test] ( @p1 INT ) RETURNS @OutputTable TABLE ( [Id] INT, [Name] NVARCHAR(50) ) AS BEGIN DECLARE @Apple AS TABLE ( [Name] NVARCHAR(50) ) INSERT INTO @Apple ([Name]) SELECT 'Apple' DECLARE @Pear AS TABLE ( [Name] NVARCHAR(50) ) INSERT INTO @Pear ([Name]) SELECT 'Pear' INSERT INTO @OutputTable ([Id], [Name]) SELECT @p1, [Name] FROM @Apple INSERT INTO @OutputTable ([Id], [Name]) SELECT @p1, [Name] FROM @Pear RETURN END;
现有EF配置(存在疑问)
// MultiStatementTest.cs public class MultiStatementTest { public int Id { get; set; } public string Name { get; set; } } // Context.OnModelCreatingPartial.cs public partial class Context { public IQueryable<MultiStatementTest> fn_multi_statement_test(int p1) { return FromExpression(() => fn_multi_statement_test(p1)); } partial void OnModelCreatingPartial(ModelBuilder modelBuilder) { // 疑问:此处不需要映射到实际表,该如何配置? // modelBuilder.Entity<MultiStatementTest>().ToTable(?); modelBuilder .HasDbFunction(typeof(Context).GetMethod(nameof(fn_multi_statement_test), new[] { typeof(int) })) .HasName("fn_multi_statement_test") .HasSchema("dbo"); } }
解决方案
核心思路:MultiStatementTest只是承载函数返回结果的DTO,并非数据库物理表,因此无需配置表映射,只需标记其为无键实体即可。
修改后的EF配置代码
// Context.OnModelCreatingPartial.cs public partial class Context { public IQueryable<MultiStatementTest> fn_multi_statement_test(int p1) { return FromExpression(() => fn_multi_statement_test(p1)); } partial void OnModelCreatingPartial(ModelBuilder modelBuilder) { // 配置为无键实体,告知EF Core该类型不对应物理表 modelBuilder.Entity<MultiStatementTest>().HasNoKey(); // 保持数据库函数的映射配置不变 modelBuilder .HasDbFunction(typeof(Context).GetMethod(nameof(fn_multi_statement_test), new[] { typeof(int) })) .HasName("fn_multi_statement_test") .HasSchema("dbo"); } }
配置说明
HasNoKey():该方法告诉EF Core,MultiStatementTest类型没有主键,也不关联数据库中的任何物理表,仅用于承载查询结果(包括表值函数的返回值)。- 移除
ToTable():完全不需要配置表映射,因为该类型并非表实体。
使用示例
在业务代码中直接调用上下文的方法即可,EF Core会自动转换为对应的SQL函数调用:
using var context = new Context(); var functionResults = context.fn_multi_statement_test(123).ToList();
生成的SQL查询示例:
SELECT [m].[Id], [m].[Name] FROM [dbo].[fn_multi_statement_test](123) AS [m]
内容的提问来源于stack exchange,提问作者User28487024
相关产品推荐
相关产品推荐

