【发布时间】:2016-02-15 00:33:10
【问题描述】:
我有一个 SQL Server 数据库,我的 MVC 应用程序可以通过 Entity Framework 6 访问它。我有一个存储过程,它执行一些总计并将其存储在临时表中,然后通过最终选择语句返回结果(简化版本):
select isnull(TotalDataShared, 0) as TotalDataShared from #main;
在某些情况下 TotalDataShared 可以为空,所以我必须检查它。 proc 结果的自动生成的 EF 实体如下所示(也简化了):
public partial class getUsageTotals_Result
{
public decimal TotalDataShared { get; set; }
}
我的 repo 方法像这样调用 proc:
public UsageTotals GetCurrentUsage(int accountId)
{
var ret = _context.getUsageTotals(accountId).First();
return new UsageTotals {
DataShared = (double)ret.TotalDataShared
};
}
当 #main 中的 TotalDataShared 不为空时,一切正常。当它为空时,我的应用程序中出现以下错误:
“getUsageTotals_Result”上的“TotalDataShared”属性不能 设置为“System.Double”值。您必须将此属性设置为 'System.Decimal' 类型的非空值。
在我看来,它忽略了 ISNULL 命令。我已经尝试将最后一个选择包装在一个表变量中,因为我过去在 EF 中从临时表返回数据时遇到过问题,但没有任何好处。
我也尝试过使用 COALESCE(),它给出了相同的结果。我也尝试在 EF 中删除和重新创建对象,但无济于事。如果它为 null (ISNULL(TotalDataShared, 4.441)),我也尝试返回一个非零浮点值,但这也不会改变任何东西。
不确定接下来要尝试什么。有什么想法吗?
更新: 添加存储过程骨架:
create proc getUsageTotals @accountid int
as
if object_id('tempdb..#main') is not null drop table #main;
create table #main (
TotalDataShared float,
)
. . .
. . .
select isnull(TotalDataShared, 4.441) as TotalDataShared from #main;
go
proc 的最后两行是 select 和 "go",所以返回值应该是 select 语句,除非我遗漏了什么。
【问题讨论】:
-
可以显示程序代码吗?
-
我添加了 sproc 骨架。这是一个简单的过程,使用普通的内部连接来获取总计并将其插入到临时表中。然后,显示最终选择。
-
isnull返回第一个参数的数据类型。这是float,映射到C#中的double。为什么将其定义为decimal?程序中有条件逻辑吗?还是从早期版本的 proc 推断出的元数据? -
是的,我最初将它与 proc 的第一个版本相匹配。但是现在已经进行了几次迭代,一切都运行良好,我无需更改任何内容,直到出现 NULL 问题。
-
您的分析不正确,因为
isnull删除了一个空值这一事实对调用代码完全不透明。它不会影响返回的数据类型,EF 无法知道这一点。您可能会发现您现在在所有呼叫中都收到错误消息。将临时表列定义更改为TotalDataShared decimal(x,y)或重做元数据发现以期望浮点数/双精度。
标签: c# sql-server entity-framework isnull