具有可为空参数的实体框架和存储过程函数导入
我注意到,当实体框架为存储过程(函数导入)生成方法时,它会测试参数是否为空,并做出如下决定:
if (contactID.HasValue)
{
contactIDParameter = new ObjectParameter("contactID", contactID);
}
else
{
contactIDParameter = new ObjectParameter("contactID", typeof(global::System.Int32));
}
我不明白它试图通过传递类型来做什么当参数为null时将参数作为参数?在这种情况下,存储过程/函数到底是如何执行的?
我自己用 SQL Profiler 做了一个测试,发现当我故意将 null 作为参数传递(通过调用 context.MyProcedure(null) 之类的方法)时,null 只是作为参数传递给 SQL Server 的存储过程。
如果对此行为进行一些澄清,我们将不胜感激。
I noticed that when Entity Framework generates a method for a stored procedure (function import), it tests to see if the parameter is null, and makes a decision like this:
if (contactID.HasValue)
{
contactIDParameter = new ObjectParameter("contactID", contactID);
}
else
{
contactIDParameter = new ObjectParameter("contactID", typeof(global::System.Int32));
}
I don't understand what its trying to do by passing the Type of the parameter as a parameter when the parameter is null? Exactly how does the stored procedure/function get executed in this case?
I did a test myself with SQL Profiler, and noticed that when I intentionally pass null as a parameter (by calling something like context.MyProcedure(null) ), null is simply passed as the parameter to the SQL server's stored procedure.
Some clarifications on this behavior would be appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我对这个问题很感兴趣,所以做了一些调查。
ObjectParameter
有两种重载 - 一种用于传递值,另一种用于传递类型。如果传递 null 作为参数值,则使用第二个,因为 EF 内部需要它。原因是函数导入必须使用 ObjectParameters 调用,而不是使用传递给包装方法的普通参数。内部 EF 调用:
正如您所见,即使 null 值也必须表示为 ObjectParameter,因为您不能简单地传递 null - 它会抛出异常。
PopulateFunctionEntityCommandParameters
使用有关类型的信息来创建正确的DbParameter
以调用存储过程。该参数的值为DBNull.Value
。所以你不必处理它。这只是基础设施。
I was interested in this question so I made some investigation.
ObjectParameter
has two overloads - one for passing value and one for passing the type. The second is used if you pass null as the parameter value because EF internally need this. The reason is that function import must be called with ObjectParameters, not with plain parameters you are passing to the wrapping method.Internally EF calls:
As you can see even null value must be represented as ObjectParameter because you can't simply pass null - it will throw exception. The
PopulateFunctionEntityCommandParameters
uses information about the type to create correctDbParameter
for calling the stored procedure. The value of that parameter isDBNull.Value
.So you don't have to deal with it. It is just infrastructure.
当您查看类
ObjectParameter
构造函数的代码时,您可以看到
ObjectParameter
有 3 个重要的私有字段:_name
(参数名称,不为 null并且不可变),_type
(参数的CLR类型,不为空且不可变),_value
(参数的值,可以更改且可为空)当第一个构造函数是使用时,这些字段都已初始化。对于第二个构造函数,
_value
字段保留为null
。在 EF 的 ExecuteFunction 中,使用私有方法 CreateEntityCommandForFunctionImport 来调用另一个更深层次的私有方法 PopulateFunctionImportEntityCommandParameters 来附加实体参数。
在
PopulateFunctionImportEntityCommandParameters
内,代表EntityCommand
中参数的EntityParameter
实例将映射到ObjectParameter
的名称和值属性代码>.该指令解释了这一切:
如果没有指定值作为参数,我们会将
DBNull
传递给 EF。When you watch the code of the class
ObjectParameter
constructorsYou can see that
ObjectParameter
has 3 important private fields:_name
(name of parameter, not null and immutable),_type
(CLR type of the parameter, not null and immutable),_value
(value of the parameter, can be changed and nullable)When the first constructor is used, these fields are all initialized. With the second constructor, the
_value
field is left to benull
.In the
ExecuteFunction
of EF, a private methodCreateEntityCommandForFunctionImport
is used which calls another even deeper private methodPopulateFunctionImportEntityCommandParameters
which attaches the entity parameters.Inside
PopulateFunctionImportEntityCommandParameters
, an instance ofEntityParameter
which represents a parameter inEntityCommand
will be mapped to the name and value's properties ofObjectParameter
.This instruction explains it all:
We pass the
DBNull
to EF if no value was specified as a parameter.