.NET EDMX导入存储过程遗漏表类型参数及调用报错问题
问题原因及解决方案
1 关于EDMX无法导入表值参数的问题
EF 6及更早版本的EDMX设计器原生不支持自动导入包含表值参数(TVP)的存储过程,所以自动生成的方法会缺失表类型参数,属于已知限制,无需修改EDMX配置,直接用以下方案调用即可,无需手动管理连接状态。
2 可行实现代码
步骤1:构造符合要求的DataTable
注意必须显式指定列类型,和SQL自定义表类型定义完全匹配,可空字段需要将C#的null转换为DBNull.Value:
DataTable data = new DataTable(); // 列类型、列名必须和SQL自定义表类型完全对应 data.Columns.Add("LowerValue", typeof(decimal)); data.Columns.Add("HigherValue", typeof(decimal)); data.Columns.Add("UnitToDeliver", typeof(decimal)); foreach (SlidingScaleProtocol.Entry entry in formData.GetEntries()) { var row = data.NewRow(); row.ItemArray = new object[] { entry.LowerValue, entry.HigherValue ?? DBNull.Value, // 可空字段必须转DBNull entry.UnitToDeliver }; data.Rows.Add(row); // 不要遗漏将行添加到DataTable }
步骤2:调用存储过程(EF自动管理连接)
使用EF内置的Database.ExecuteSqlCommand方法,无需手动开闭连接:
// 构造表值参数 var newEntriesParam = new SqlParameter("@newEntries", SqlDbType.Structured) { TypeName = "oprSlidingScaleProtocolEntrySet", // 必须和SQL中定义的表类型名完全一致 Value = data }; // 执行存储过程 db.Database.ExecuteSqlCommand( "EXEC oprUpdateSlidingScaleProtocol @PrescriptionId, @newEntries", new SqlParameter("@PrescriptionId", prescriptionId), newEntriesParam );
3 之前报错的原因说明
- 直接用
SqlCommand报错是因为你获取的EF上下文默认连接是关闭状态,EF仅在执行自身封装的方法时才会自动管理连接开闭,手动创建SqlCommand需要额外调用Open()方法,改用ExecuteSqlCommand即可避免该问题 ObjectContext.ExecuteFunction报错是因为ObjectParameter不支持Structured类型的表值参数,该方法本身不适用当前场景- 如果未指定DataTable的列类型,或者未将构造的行添加到DataTable,也会引发参数类型不匹配错误
内容的提问来源于stack exchange,提问作者B. Bergeron
相关产品推荐
相关产品推荐

