gpt4 book ai didi

c# - 存储过程有时返回short,有时返回int

转载 作者:太空狗 更新时间:2023-10-29 18:35:19 24 4
gpt4 key购买 nike

我正在使用遗留代码库,需要调用一个不允许修改的存储过程。此存储过程返回一行或多行验证数据。

结果集示例(两列,代码和文本):

0 "success"

3 "short error"
4 "detailed error"

在程序本身中,消息被简单地选择为:

Select 0 as code, 'success' as text

问题:

我正在使用 Entity Framework 将此存储过程的结果映射到自定义类:

public class ValidationResult
{
public int code { get; set; }
public string text { get; set; }
}

调用本身:

var result = context.Database.SqlQuery<ValidationResult>(@"old_sproc").ToList();

我已经编写了一些集成测试,并注意到当该过程返回成功消息时,0 显示为 short。当它返回一个非零消息时,它会以 int 的形式出现。我假设将 code 设置为 int,short 会适合。不幸的是,我的成功测试出现以下异常:

The specified cast from a materialized 'System.Int16' type to the 'System.Int32' type is not valid.

当我将 code 切换为 short 以使我的成功测试通过时,我的失败测试失败并出现以下异常:

The specified cast from a materialized 'System.Int32' type to the 'System.Int16' type is not valid.

ADO.NET 是答案

一个解决方案是回退到 ADO.NET 的 SqlDataReader 对象,所以我将其作为回退解决方案。不过,我想知道我是否可以在 EF 方面做些什么来使它正常工作。

最佳答案

(这是 my previous answer 的后续。它只与 及以后相关。)

简答:

var sql = "EXECUTE old_sproc WITH RESULT SETS ((code INT, text VARCHAR(MAX)))";
var result = context.Database.SqlQuery<ValidationResult(sql).ToList();

此答案中采用的方法:

这个答案将跟随您的脚步并使用 SqlQuery 来执行您的存储过程。 (为什么不采用完全不同的方法?因为可能没有任何替代方法。我将在下面进一步探讨。)

让我们从观察您当前的代码开始:

var result = context.Database.SqlQuery<ValidationResult>(@"old_sproc").ToList();

查询文本 "old_sproc" 实际上是 "EXECUTE old_sproc" 的 T-SQL 缩写。我提到这一点是因为很容易认为 SqlQuery 以某种方式特殊处理存储过程的名称;但是不,这实际上是一个常规的 T-SQL 语句。

在这个答案中,我们只会稍微修改您当前的 SQL。

使用 WITH RESULT SETS 子句的隐式类型转换:

那么让我们继续您已经在做的事情:通过 SqlQueryEXECUTE 存储过程。从 SQL Server 2012 开始,EXECUTE statement支持名为 WITH RESULT SETS 的可选子句,它允许您指定希望返回的结果集。如果实际结果集不符合该规范,SQL Server 将尝试执行隐式类型转换。

在您的情况下,您可以这样做:

var sql = "EXECUTE old_sproc WITH RESULT SETS ((code INT, text VARCHAR(MAX)))";
var result = context.Database.SqlQuery<ValidationResult(sql).ToList();

添加的子句声明您希望返回一个包含 code INTtext VARCHAR(MAX) 列的结果集。重要的一点是 code INT:如果存储过程恰好为 code 生成 SMALLINT 值,SQL Server 将执行到 的转换INT 给你。

隐式转换可能会让您走得更远:例如,您可以将 code 指定为 VARCHAR(...) 甚至 NUMERIC(...) (并将您的 C# 属性分别更改为 stringdecimal)。

如果您正在使用 Entity Framework 的 SqlQuery 方法,它不太可能比这更整洁。

为了快速引用,以下是链接到 MSDN 引用页面的一些引述:

"The actual result set being returned during execution can differ from the result defined using the WITH RESULT SETS clause in one of the following ways: number of result sets, number of columns, column name, nullability, and data type."

"If the data types differ, an implicit conversion to the defined data type is performed."

我必须编写 SQL 查询吗?难道没有另一种(更多 ORM)方式吗?

据我所知没有。

Entity Framework 最近一直在朝着“代码优先”的方向发展(在撰写本文时它是第 6 版),并且这种趋势可能会继续下去。

Julie Lerman & Rowan Miller 合着的“Programming Entity Framework Code First”一书(O'Reilly 2012 年出版)有一章很短“Working with Stored Procedures”,其中包含两个代码示例;两者都使用 SqlQuery 来映射存储过程的结果集。

我想如果这两位 EF 专家没有展示另一种映射存储过程的方法,那么 EF 目前可能没有提供任何替代 SqlQuery 的方法。

(附言:不可否认,OP 的主要问题不是存储过程本身;它让 EF 执行自动类型转换。即便如此,除了此处显示的方法,我不知道还有其他方法。)

关于c# - 存储过程有时返回short,有时返回int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29242190/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com