FunctionImport在实体框架4中的问题

时间:2010-10-01 08:39:54

标签: entity-framework entity

我正在使用实体框架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);

当我运行它时,我收到以下错误:

  

商店退回的数据阅读器   数据提供者没有足够的   请求查询的列。

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

由于

2 个答案:

答案 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));
    ...