C# 实体框架EF4.1-存储过程;在容器中找不到“;

C# 实体框架EF4.1-存储过程;在容器中找不到“;,c#,sql-server-2008,entity-framework-4.1,sql-server-express,appharbor,C#,Sql Server 2008,Entity Framework 4.1,Sql Server Express,Appharbor,我的数据库中有一个SP。对于EF4.1,使用 从数据模型导入函数后,对存储过程的引用在我的开发环境中可以正常工作。但是当发布到服务器时,它会失败,并显示如下消息:在容器“TallyJ2Entities”中找不到FunctionImport“SqlSearch”。所有其他数据访问都正常工作 似乎在生产中,EF4配置的某些方面被遗忘了 数据库是相同的,两台服务器都是SQL 2008(本地是Express SP1 10.50.2500,主机是Express RTM 10.50.1600) 我甚至将ED

我的数据库中有一个SP。对于EF4.1,使用

从数据模型导入函数后,对存储过程的引用在我的开发环境中可以正常工作。但是当发布到服务器时,它会失败,并显示如下消息:在容器“TallyJ2Entities”中找不到FunctionImport“SqlSearch”。所有其他数据访问都正常工作

似乎在生产中,EF4配置的某些方面被遗忘了

数据库是相同的,两台服务器都是SQL 2008(本地是Express SP1 10.50.2500,主机是Express RTM 10.50.1600)

我甚至将EDMX编辑器直接指向生产数据库,并进行了更新。结果在开发中运行良好,但在服务器上以同样的方式失败

其他类似的问题也无济于事。其他人似乎也有类似的问题

有什么建议吗

更新:我发现在调试模式下部署主机时,问题就消失了

在DbContext派生的类中,我将以下代码放入:

((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace
var findFunction = metadataWorkspace.GetItems(DataSpace.SSpace)
            .SelectMany(gi => gi.MetadataProperties)
            .Where(m=> Equals(m.Value, "SqlSearch"))
            .Select(m => "Found {0}".FilledWith(m.Value))
            .FirstOrDefault();

当我记录
findFunction
结果时,发现服务器(在发布模式下)没有找到它,而在开发过程中找到了它。

如果使用EF 4.1及以上版本,请在Context.cs文件中将“ObjectParameter”更改为“SqlParameter”,将“ExecuteFunction”更改为“executestrequery”

“ExecuteStoreQuery”方法还希望您将参数名称添加到存储过程的前面。请在下面查找代码片段:

var param1Parameter = param1 != null ?
new SqlParameter("param1", param1) :
new SqlParameter("param1", typeof(string));

var param2Parameter = param2 != null ?
new SqlParameter("param2", param2) :
new SqlParameter("param2", typeof(int));

return ((IObjectContextAdapter)this).ObjectContext.ExecuteStoreQuery<sp_TestSproc_Result>("sp_TestSproc @param1, @param2", param1Parameter, param2Parameter);
var param1Parameter=param1!=无效的
新的SqlParameter(“param1”,param1):
新的SqlParameter(“param1”,typeof(string));
var PARAME2PARAMETER=param2!=无效的
新的SqlParameter(“param2”,param2):
新的SqlParameter(“param2”,typeof(int));
返回((IObjectContextAdapter)this.ObjectContext.ExecuteStoreQuery(“sp_TestSproc@param1,@param2”,param1Parameter,param2Parameter”);
如果使用模板生成代码,您可能会发现下面的代码段也很有用。即,我修改了标准的“Fluent TT”生成器,以适应EF 4.3:

    void WriteFunctionImport(EdmFunction edmFunction, bool includeMergeOption)
    {
        var parameters = FunctionImportParameter.Create(edmFunction.Parameters, Code, EFTools);
        var paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
        var returnType = edmFunction.ReturnParameter == null ? null : EFTools.GetElementType(edmFunction.ReturnParameter.TypeUsage);
        var processedReturn = returnType == null ? "int" : "ObjectResult<" + MultiSchemaEscape(returnType) + ">";

        if (includeMergeOption)
        {
            paramList = Code.StringAfter(paramList, ", ") + "MergeOption mergeOption";
        }
    #>

        <#=AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction))#> <#=processedReturn#> <#=Code.Escape(edmFunction)#>(<#=paramList#>)
        {
    <#+
            if(returnType != null && (returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType ||
                                      returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType))
            {
    #>
            ((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(<#=MultiSchemaEscape(returnType)#>).Assembly);

    <#+
            }

            foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
            {
                var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
                var notNullInit = "new SqlParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")";
                var nullInit = "new SqlParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + parameter.RawClrTypeName + "))";
    #>
            var <#=parameter.LocalVariableName#> = <#=isNotNull#> ?
                <#=notNullInit#> :
                <#=nullInit#>;

    <#+
            }

            var genericArg = returnType == null ? "" : "<" + MultiSchemaEscape(returnType) + ">";
            var callParams = Code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()));
            var spParams = Code.StringBefore("@", String.Join(", @", parameters.Select(p => p.EsqlParameterName).ToArray()));

            if (includeMergeOption)
            {
                callParams = ", mergeOption" + callParams;
            }
    #>
            return ((IObjectContextAdapter)this).ObjectContext.ExecuteStoreQuery<#=genericArg#>("<#=edmFunction.Name#> <#=spParams#>"
                        <#=callParams#>);
        }
    <#+
        if(!includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType)
        {
            WriteFunctionImport(edmFunction, true);
        }
    }
void WriteFunctionImport(EdmFunction EdmFunction,bool includeMergeOption)
{
var参数=FunctionImportParameter.Create(edmFunction.parameters、代码、EFTools);
var paramList=String.Join(“,”,parameters.Select(p=>p.FunctionParameterType+“”+p.FunctionParameterName.ToArray());
var returnType=edmFunction.ReturnParameter==null?null:EFTools.GetElementType(edmFunction.ReturnParameter.TypeUsage);
var processedReturn=returnType==null?“int”:“ObjectResult”;
if(includemerge选项)
{
paramList=Code.StringAfter(paramList,“,”)+“MergeOption MergeOption”;
}
#>
()
{
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof().Assembly);
p、 需求(可变)
{
var isNotNull=parameter.IsNullableOfT?parameter.FunctionParameterName+“.HasValue”:parameter.FunctionParameterName+“!=null”;
var notNullInit=“新建SqlParameter(\”“+parameter.EsqlParameterName+”\”,“+parameter.FunctionParameterName+”);
var nullInit=“新的SqlParameter(\”“+parameter.EsqlParameterName+”\”,typeof(“+parameter.RawClrTypeName+”)”;
#>
var=?
:
;
p、 ExecuteParameterName.ToArray());
var spParams=Code.StringBefore(“@”,String.Join(“,@”,parameters.Select(p=>p.EsqlParameterName.ToArray());
if(includemerge选项)
{
callParams=“,mergeOption”+callParams;
}
#>
返回((IObjectContextAdapter)this.ObjectContext.ExecuteStoreQuery(“”)
);
}

我们发现这是由于连接字符串错误造成的

EF需要一个如下所示的连接字符串:

<connectionStrings>
  <add name="MyModel_Entities" connectionString="metadata=res://*/Models.MyModel.csdl|res://*/Models.MyModel.ssdl|res://*/Models.MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=192.168.1.200;initial catalog=MyDb_Live;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>
<add name="MyModel_Entities" connectionString="Data Source=.;Initial Catalog=MyDb_Live;Integrated Security=SSPI;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />

其中显示MyModel,它应该与.edmx模型文件的名称相对应

如果您从其他地方复制了connectionString,它可能如下所示:

<connectionStrings>
  <add name="MyModel_Entities" connectionString="metadata=res://*/Models.MyModel.csdl|res://*/Models.MyModel.ssdl|res://*/Models.MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=192.168.1.200;initial catalog=MyDb_Live;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>
<add name="MyModel_Entities" connectionString="Data Source=.;Initial Catalog=MyDb_Live;Integrated Security=SSPI;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />

请特别注意ConnectionString末尾的providerName中的差异

注意:我们正在使用EF 6.1,但我相信这也适用于早期版本。
如果您修复了连接字符串,我们发现您可以继续使用T4模板生成的代码。您不需要将ObjectParameter切换为SqlParameter,将ExecuteFunction切换为ExecuteStoreQuery。

我认为连接字符串不是问题。在我的情况下,我无法调用store过程,但我可以将数据写入数据库。这意味着我们的连接是正确的。

关于这一点,似乎有很多问题:谢谢。但这些想法对我都不起作用。谢谢……我将在下周或两周内尝试。希望能够摆脱调试模式!太好了,谢谢!不知道我自己花了多长时间才发现这一点!我正在尝试这样做类似的东西,但我没有sp,我有一个TVF。我得到一个错误,说:“函数不是sp,它是TVF”。你知道如何解决这个问题吗?我同意…连接字符串格式对EF非常重要。感谢你强调这一点。我在项目中添加了2个EDMX,我只是复制粘贴了连接字符串,这就是我的解决方案。因为我使用了错误的“MyModel”它在另一个容器中查找存储过程。谢谢