FunctionImport在实体框架4中的问题

Bre*_*ogt 9 entity entity-framework

我正在使用实体框架4.

我有一个存储过程只更新我的表中的一个值,即应用程序状态ID.所以我创建了一个如下所示的存储过程:

ALTER PROCEDURE [dbo].[UpdateApplicationState]
(
   @ApplicationID INT,
   @ApplicationStateID INT
)

AS

BEGIN

   UPDATE
      [Application]
   SET
      ApplicationStateID = @ApplicationStateID
   WHERE
      ApplicationID = @ApplicationID;

END
Run Code Online (Sandbox Code Playgroud)

我创建了一个名为UpdateApplicationState的函数导入.我最初将其返回类型设置为null,但之后它不是在上下文中创建的.所以我将其返回类型更改为int.现在它是在上下文中创建的.从我的存储过程中返回一些东西是明智的吗?

这是我的ApplicationRepository类中的方法:

public void UpdateApplicationState(int applicationID, int applicationStateID)
{
   var result = context.UpdateApplicationState(applicationID, applicationStateID);
}
Run Code Online (Sandbox Code Playgroud)

以下是我在该视图中对此方法的调用代码:

applicationRepository.UpdateApplicationState(id, newApplicationStateID);
Run Code Online (Sandbox Code Playgroud)

当我运行它然后我收到以下错误:

商店数据提供程序返回的数据读取器没有足够的列用于请求的查询.

有什么想法/建议我能做些什么才能让它发挥作用?

谢谢

Joh*_*ika 20

要使POCO使用返回null的函数导入,您可以像这样自定义.Context.tt文件.

找到"函数导入"命名的区域(与region.Begin("函数导入")开头的部分,以及与region.End()结束)在.Context.tt文件,并用以下替换整段:

    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();
Run Code Online (Sandbox Code Playgroud)

我在这里做的不是忽略所有返回null的函数导入,而是创建一个返回null的方法.我希望这是有帮助的.


Mor*_*avi 16

这是因为您实际上没有从存储过程中返回任何内容.在SP中添加如下所示的行(SELECT @@ ROWCOUNT),它将正确执行.

BEGIN    
    ...

    SELECT @@ROWCOUNT
END
Run Code Online (Sandbox Code Playgroud)

虽然此解决方案将解决您的问题并实际返回SP的受影响行数,但我不清楚为什么这对您来说是一个问题:

我最初将其返回类型设置为null,但之后它不是在上下文中创建的.

执行函数导入时,可以选择"无"作为返回类型,它将在ObjectContext上生成一个返回类型为int的新方法.该方法基本上执行在数据源中定义的存储过程; 丢弃从函数返回的任何结果; 并返回受执行影响的行数.

编辑:为什么在POCO场景中忽略没有返回值的函数:

钻入到ADO.NET附带的ObjectContext T4模板文件C#POCO实体生成器揭示了为什么在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));
    ...
Run Code Online (Sandbox Code Playgroud)