我前几天注意到了这个错误,今天再次确认了它。还发现其他人有这个问题。
实体框架将不返回任何结果(当它应该返回时),并且在以下场景中不会抛出异常:
-
使用SqlQuery方法执行存储过程
-
至少提供一个可选参数
-
至少跳过一个可选参数
我所说的“跳过”是指进程签名中参数的顺序。只要你不跳过任何可选参数,就没有问题;只有当您提供了一个可选参数,该参数位于另一个未包含的参数之后。
可能还有其他变体。例如,我怀疑如果您在跳过的可选参数之后提供了一个必需的参数,也会出现同样的问题。。。但对此并不确定。
现在考虑这个场景:
我在进程签名的末尾添加了一个新的可选参数。现在我更新了一个SqlQuery()调用并添加了新的参数,但由于前面提到的错误,我没有得到任何结果。我有两个选择:1)我可以添加我遗漏的所有可选参数。或者2)我可以将新参数移到签名中的左边,这样我就不再跳过SqlQuery()调用中的任何参数。
当然,2)的问题在于,这可能会破坏正在跳过该参数的现有代码。所以,实际上,我唯一的选择似乎是一直包括所有参数,这完全违背了最初拥有可选参数的全部目的。
有什么方法可以解决这个问题吗?或者如果我使用实体框架调用存储的proc,我只是不得不始终传入所有参数吗?
编辑:我看到的另一个潜在问题是,它不允许我让SQL使用默认值,因为没有可以传递给SQL的“值”来告诉它使用默认值。你告诉它通过不传递值来使用默认值。。。EF似乎没有正确处理。
编辑2:
最小可复制代码:
CREATE PROC MyProc @p1 int, @p2 int = 0, @p3 int = 0
as
select * from MyTable
where p1 = @p1
and (@p2 = 0 or p2 = @p2)
and (@p3 = 0 or p3 = @p3)
C#代码:
List<MyObject> SomeMethod(int p1, int p3)
{
return db.Database.SqlQuery<MyObject>("dbo.MyProc @p1, @p3",
new SqlParameter("@p1", p1),
new SqlParameter("@p3", p3)
).ToList();
}