我正在使用实体框架4。
我有一个存储过程只更新表中的一个值,即应用程序状态ID。所以我创建了一个如下所示的存储过程:
ALTER PROCEDURE [dbo].[UpdateApplicationState]
(
@ApplicationID INT,
@ApplicationStateID INT
)
AS
BEGIN
UPDATE
[Application]
SET
ApplicationStateID = @ApplicationStateID
WHERE
ApplicationID = @ApplicationID;
END
我创建了一个名为UpdateApplicationState的函数导入。我最初将其返回类型设置为null,但之后它不是在上下文中创建的。所以我将其返回类型更改为int。现在它是在上下文中创建的。从我的存储过程中返回一些东西是明智的吗?
这是我的ApplicationRepository类中的方法:
public void UpdateApplicationState(int applicationID, int applicationStateID)
{
var result = context.UpdateApplicationState(applicationID, applicationStateID);
}
以下是我在该视图中对此方法的调用代码:
applicationRepository.UpdateApplicationState(id, newApplicationStateID);
当我运行它时,我收到以下错误:
商店退回的数据阅读器 数据提供者没有足够的 请求查询的列。
有什么想法/建议我可以做些什么才能让它发挥作用?
由于
答案 0 :(得分:20)
要让POCO使用返回null的函数导入,您可以像这样自定义.Context.tt文件。
在.Context.tt文件中找到“Function Imports”命名区域(以region.Begin(“Function Imports”)开头的部分;以region.End();)结尾,并将整个部分替换为以下内容:
region.Begin("Function Imports");
foreach (EdmFunction edmFunction in container.FunctionImports)
{
var parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef);
string paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
var isReturnTypeVoid = edmFunction.ReturnParameter == null;
string returnTypeElement = String.Empty;
if (!isReturnTypeVoid)
returnTypeElement = code.Escape(ef.GetElementType(edmFunction.ReturnParameter.TypeUsage));
#>
<# if (isReturnTypeVoid) { #>
<#=Accessibility.ForMethod(edmFunction)#> void <#=code.Escape(edmFunction)#>(<#=paramList#>)
<# } else { #>
<#=Accessibility.ForMethod(edmFunction)#> ObjectResult<<#=returnTypeElement#>> <#=code.Escape(edmFunction)#>(<#=paramList#>)
<# } #>
{
<#
foreach (var parameter in parameters)
{
if (!parameter.NeedsLocalVariable)
{
continue;
}
#>
ObjectParameter <#=parameter.LocalVariableName#>;
if (<#=parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"#>)
{
<#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", <#=parameter.FunctionParameterName#>);
}
else
{
<#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", typeof(<#=parameter.RawClrTypeName#>));
}
<#
}
#>
<# if (isReturnTypeVoid) { #>
base.ExecuteFunction("<#=edmFunction.Name#>"<#=code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>);
<# } else { #>
return base.ExecuteFunction<<#=returnTypeElement#>>("<#=edmFunction.Name#>"<#=code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>);
<# } #>
}
<#
}
region.End();
我在这里做的不是忽略所有返回null的函数导入,而是创建一个返回null的方法。我希望这有用。
答案 1 :(得分:16)
这是因为您实际上没有从存储过程中返回任何内容。在SP中添加如下所示的行( SELECT @@ ROWCOUNT ),它将正常执行。
BEGIN
...
SELECT @@ROWCOUNT
END
虽然此解决方案可以解决您的问题并实际返回您的SP影响的行数,但我不清楚为什么这对您来说是个问题:
我最初将其返回类型设置为null,但之后并未在上下文中创建。
执行功能导入时,可以选择“无”作为返回类型,它将在ObjectContext上生成一个返回类型为 int 的新方法。该方法基本上执行在数据源中定义的存储过程;丢弃从函数返回的任何结果;并返回受执行影响的行数。
编辑:为什么在POCO场景中忽略没有返回值的函数:
钻入 ADO.NET C#POCO实体生成器附带的 ObjectContext T4模板文件,揭示了为什么在ObjectContext类中看不到你的函数:简单地忽略它!它们转移到生成函数的foreach循环中的下一次迭代。
解决方法是更改T4模板以实际生成函数的方法而不返回类型,或者只返回基于第一个解决方案的函数。
region.Begin("Function Imports");
foreach (EdmFunction edmFunction in container.FunctionImports)
{
var parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef);
string paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
// Here is why a Function without return value is ignored:
if (edmFunction.ReturnParameter == null)
{
continue;
}
string returnTypeElement = code.Escape(ef.GetElementType(edmFunction.ReturnParameter.TypeUsage));
...