为什么从存储过程导入的函数的参数顺序发生了变化?

时间:2010-11-11 17:39:17

标签: entity-framework entity-framework-4

我在SQL Sever 2008中有一个存储过程,如:

ALTER PROCEDURE [dbo].[mySP]
@FirstName As varchar(30),  
@LastName As varchar(30),   
@ID As int 
As 
Begin
--......
End

然后在EF中将此SP导入为以下函数:

public ObjectResult<Nullable<global::System.Int32>> MyFunc(global::System.String LastName,  global::System.String FirstName,Nullable<global::System.Int32> ID)
{
//....
}

它可以长时间正常工作。

然后我今天用“从数据库更新”向EF edmx添加一些新东西,功能参数改变了!它成了:

public ObjectResult<Nullable<global::System.Int32>> MyFunc(global::System.String LastName,Nullable<global::System.Int32> ID,  global::System.String FirstName)
{
//....
}

很难相信它。我已经有很多代码来调用这个函数,它运行正常。现在所有这些都没有用。即使我可以手动更改参数,但也许它可以使用生成的代码返回原始订单!

如何解决此问题。

4 个答案:

答案 0 :(得分:4)

在存储过程中使用ALTER PROCEDURE时会发生此错误,并且不会出现在所有情况下。

我们已经能够显示参数顺序由SQL控制,并且在更改存储的proc参数列表(例如添加参数,尤其是具有默认值的参数)之后,然后使用“从数据库更新模型”实体模型,参数顺序变为按字母顺序排列。一种可能性是SQL有一种机制,用于在添加可选参数时保持与编译过程的兼容性,这表现为观察到的行为。

您需要在数据库中修复它。我们能够恢复正确参数顺序的唯一方法是DROPCREATE存储过程,然后更新模型。对数据库的更新不会对存储模型进行任何更改。

我们正在使用SQL 2000。

答案 1 :(得分:0)

从EF4开始,默认代码生成也基于T4模板。通过深入研究T4,我们可以看到它如何为函数导入生成代码:

foreach (EdmFunction edmFunction in container.FunctionImports)
{
    IEnumerable<FunctionImportParameter> parameters = 
FunctionImportParameter.Create(edmFunction.Parameters, code, ef);
    string paramList = string.Join(", ", parameters.Select(p => 
        p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
...
所以它完全基于您的SSDL架构在您的模型下的样子。 例如,对于 Adventureworks 数据库中的 uspUpdateEmployeePersonalInfo SP:

CREATE PROCEDURE [HumanResources].[uspUpdateEmployeeHireInfo]
    @EmployeeID [int], 
    @Title [nvarchar](50), 
    @HireDate [datetime], 
    @RateChangeDate [datetime], 
    @Rate [money], 
    @PayFrequency [tinyint], 
    @CurrentFlag [dbo].[Flag] 

SSDL如下所示:

<Function Name="uspUpdateEmployeePersonalInfo" Aggregate="false" 
BuiltIn="false" NiladicFunction="false" IsComposable="false"
 ParameterTypeSemantics="AllowImplicitConversion" Schema="HumanResources">
          <Parameter Name="EmployeeID" Type="int" Mode="In" />
          <Parameter Name="NationalIDNumber" Type="nvarchar" Mode="In" />
          <Parameter Name="BirthDate" Type="datetime" Mode="In" />
          <Parameter Name="MaritalStatus" Type="nchar" Mode="In" />
          <Parameter Name="Gender" Type="nchar" Mode="In" />
</Function>
它将导致在ObjectContext中生成此代码:

public int UpdateEmployeePersonalInfo(Nullable<global::System.Int32> employeeID, 
                                     global::System.String nationalIDNumber, 
                                     Nullable<global::System.DateTime> birthDate,
                                     global::System.String maritalStatus, 
                                     global::System.String gender)

我的猜测是模型中SSDL模式中属性的顺序已更改,EF会生成新代码以匹配该顺序。因此,在验证参数是在数据库内的SP中以所需顺序声明后,尝试从模型中删除SP并再次从数据库更新模型,您将看到生成的方法代码将相应更改。

答案 2 :(得分:0)

我们看到很多存储过程都会发生此问题,但我们无法确定原因。任何关于此的新信息都将提供很多帮助。

我已经看到它在存储过程中发生了很多输入和输出参数。此外,在更新表单数据库命令,当存储过程没有更改,并且edmx文件没有更改但设计器导致参数重新排序。

答案 3 :(得分:0)

验证数据库的兼容级别是否低于90

  

sp_dbcmptlevel'your_database_name'

如果报告的值低于90,则运行

  

sp_dbcmptlevel'your_database_name',90

Thanks to lajones in Codeplex