如何通过Entity Framework 6向SQL Server表值函数传递整数列表
在Entity Framework 6(数据库优先)中向表值函数传递整数列表
我之前也碰到过一模一样的需求,折腾了一阵才摸清楚门道,下面是亲测有效的一步步解决方案:
1. 确认SQL Server端的基础对象已就绪
首先你得确保已经在数据库里创建好这两个核心对象:
- 表值类型(比如我习惯命名为
dbo.IntList,只包含一个int类型的列,列名比如叫Value) - 接收该表值类型参数的表值函数(比如
dbo.GetDataFromIntList(@Ids dbo.IntList READONLY),函数内部用这个参数做筛选或关联逻辑)
2. 将表值类型和表值函数导入EDMX模型
打开你的EDMX文件:
- 右键空白区域,选择Update Model from Database...
- 在弹出的更新向导里,展开Table-valued Functions和User-defined Table Types,勾选你需要导入的函数和表值类型
- 点击Finish完成模型更新
3. 创建对应表值类型的.NET类
EF6不会自动生成表值类型的实体类,所以得手动写一个和SQL表值类型结构完全匹配的类:
public class IntListType { // 这里的属性名必须和SQL表值类型的列名完全一致,大小写也要对应 public int Value { get; set; } }
4. 修改函数导入的参数类型
打开EDMX的Model Browser(右键EDMX文件就能找到这个选项):
- 在Function Imports节点下找到你的表值函数
- 右键函数选择Edit...
- 在编辑对话框里,把参数的默认类型(通常是
Object)改成IEnumerable<IntListType>(如果找不到这个类型,先确保你刚写的类已经编译通过,且命名空间和EDMX的模型命名空间匹配) - 点击OK保存修改
5. 在代码中调用表值函数
现在就可以像调用普通EF函数一样传参了,只需要把整数列表转换成表值类型对应的类列表:
// 假设这是你要传递的整数列表 var myIntegerList = new List<int> { 101, 202, 303, 404 }; // 转换成适配表值类型的对象列表 var tvpList = myIntegerList.Select(id => new IntListType { Value = id }).ToList(); // 调用EF中的表值函数 using (var db = new YourDbContext()) { var queryResult = db.GetDataFromIntList(tvpList).ToList(); // 后续处理查询结果即可 }
备选方案:直接用SQL原生调用(避坑用)
如果EDMX导入过程中出现奇怪的bug(比如参数类型死活改不了),可以用DbRawSqlQuery直接调用,这种方式更接近ADO.NET,但依然在EF上下文范围内:
var myIntegerList = new List<int> { 101, 202, 303, 404 }; // 创建结构化参数 var tvpParam = new SqlParameter("@Ids", SqlDbType.Structured) { Value = myIntegerList.Select(id => new { Value = id }).ToList(), TypeName = "dbo.IntList" // 必须指定SQL Server中表值类型的全称 }; using (var db = new YourDbContext()) { var queryResult = db.Database.SqlQuery<YourEntityType>( "SELECT * FROM dbo.GetDataFromIntList(@Ids)", tvpParam ).ToList(); }
几个注意点
- 项目目标框架必须是**.NET Framework 4.5及以上**,EF6对表值类型的支持依赖这个版本
- 表值类型的列名和.NET类的属性名必须完全一致,否则会出现映射失败
- 每次更新EDMX模型后,最好检查一下函数导入的参数类型,自动导入偶尔会把类型重置回默认值
内容的提问来源于stack exchange,提问作者So_oP
相关产品推荐
相关产品推荐

