如何在EF4中正确使用InOut ObjectParameter?

Mik*_*rie 5 c# entity-framework entity-framework-4

我最近有理由除了我的存储过程返回的表格数据之外还带回一个值.由于EF不支持具有多个结果集的存储过程,我想我可以通过输出参数完成此操作.但是,使用这种方法我遇到了一个问题,即我只获得了一些数值字段的舍入值.

我的存储过程的参数声明为:

@MyValue    numeric(19,6) output
Run Code Online (Sandbox Code Playgroud)

调用映射函数时,我有:

var myValue = new ObjectParameter("MyValue", typeof(decimal));
List<MyResultItem> results = this.ObjectContext.CallMyStoredProc(someId, myValue).ToList();
Run Code Online (Sandbox Code Playgroud)

这总是返回舍入为整数的值(即,刻度为零).

我首先通过手动添加Precision和Scale属性手动编辑底层XML到.edmx来解决这个问题:

<Parameter Name="MyValue" Type="numeric" Mode="InOut" Precision="19" Scale="6" />
Run Code Online (Sandbox Code Playgroud)

不出所料,下次我执行"从数据库更新模型"时,这完全被丢弃了.

我似乎通过更新我的声明来更可靠地修复它ObjectParameter:

var myValue = new ObjectParameter("MyValue", 999999999.999999M);
Run Code Online (Sandbox Code Playgroud)

然而,这似乎非常像一个黑客,我担心未来的问题(即使它只是关于这个神奇数字的维护).是否有更好,更可靠的方法在Entity Framework中使用输出参数?

Mik*_*rie 0

现在,我最终在更多地方需要它,所以我为其创建了一个辅助方法:

/// <summary>
/// Get the maximum allowed value for a SQL numeric of the specified scale and precision.
/// </summary>
/// <param name="scale">The scale.</param>
/// <param name="precision">The precision.</param>
/// <returns>Decimal representing the maximum value for the specified numeric.</returns>
public static decimal SqlNumericMax(int scale, int precision)
{
    return (decimal)Math.Pow(10, (scale - precision)) - (decimal)Math.Pow(10, (-1 * precision));
}
Run Code Online (Sandbox Code Playgroud)

这并不能免除在代码中使用幻数的问题,但至少它确实有助于提供您在代码中看到的内容与您在数据库中看到的内容之间的精确匹配。(即,对于numeric(19,6)存储过程参数,您将调用Utility.SqlNumericMax(19, 6),因此关系更加明显。)

看起来在存储过程调用之前为参数提供最大值仍然是调用正确填充结果的最佳且最可靠的方法。