Gle*_*tle 7 c# sql-server-express sql-server-2008 entity-framework-4.1 appharbor
我的数据库中有一个SP.对于EF4.1,使用DbContext API.
从数据模型导入函数后,对存储过程的引用在我的开发环境中正常工作.但是当发布到服务器时,它会失败并显示如下消息:在容器'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();
Run Code Online (Sandbox Code Playgroud)
当我记录findFunction
结果时,事实证明服务器(在发布模式下)没有找到它,而在开发中,它被找到了.
Kwe*_*wex 19
如果使用EF 4.1及更高版本,请在Context.cs文件中将"ObjectParameter"更改为"SqlParameter",将"ExecuteFunction"更改为"ExecuteStoreQuery".
"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);
Run Code Online (Sandbox Code Playgroud)
如果使用模板生成代码,您可能会发现下面的代码段也很有用.即我已经修改了标准的"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);
}
}
Run Code Online (Sandbox Code Playgroud)
我们发现这是由于错误的connectionString引起的.
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="data source=192.168.1.200;initial catalog=MyDb_Live;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
Run Code Online (Sandbox Code Playgroud)
它说MyModel,它应该与.edmx模型文件的名称相对应.
如果您从其他地方复制了connectionString,它可能如下所示:
<add name="MyModel_Entities" connectionString="Data Source=.;Initial Catalog=MyDb_Live;Integrated Security=SSPI;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />
Run Code Online (Sandbox Code Playgroud)
请特别注意connectionStrings末尾的providerName的区别.
注意我们使用的是EF 6.1,但我相信这也适用于早期版本.如果您修复了连接字符串,我们发现您可以继续使用T4模板生成的代码.您不需要将ObjectParameter切换为SqlParameter,将ExecuteFunction切换为ExecuteStoreQuery.
归档时间: |
|
查看次数: |
15577 次 |
最近记录: |