c#-在System.Data.Entity.Database上第二次调用ExecuteSqlCommand时出错
作者:互联网
我使用的是EF5代码优先,因此我有一个DbContext,它的Database属性的类型为System.Data.Entity.Database.
我发现的问题是,当使用相同的参数多次调用相同的SP时,它会引发异常消息:“该SqlParameter已被另一个SqlParameterCollection包含”.
这可以用下面的代码演示.首先创建一个DbContext派生并将其连接到数据库.代码中的存储过程不必存在.对SP的第一次调用将错误地指出SP不存在,但是,第二个例外是我们感兴趣的那个.
var pa = new SqlParameter[]
{
new SqlParameter("@Name", SqlDbType.NVarChar) { Value = "test" }
};
var dc = new MyWebContext(); // derived from DbContext
try
{
dc.Database.ExecuteSqlCommand("spImport @Name", pa);
}
catch { }
dc.Database.ExecuteSqlCommand("spImport @Name", pa); // fails with "The SqlParameter is already contained by another SqlParameterCollection"
我确实有时需要两次或多次调用具有相同参数的同一SP.这是一个有效的要求.我的假设是,调用ExecuteSqlCommand是非常短暂的,应该可以在同一上下文中多次执行.
似乎上下文挂在第一个调用的参数信息上,从而导致第二个问题.
这是堆栈跟踪:
at System.Data.SqlClient.SqlParameterCollection.Validate(Int32 index, Object value)
at System.Data.SqlClient.SqlParameterCollection.AddRange(Array values)
at System.Data.Objects.ObjectContext.CreateStoreCommand(String commandText, Object[] parameters)
at System.Data.Objects.ObjectContext.ExecuteStoreCommand(String commandText, Object[] parameters)
at System.Data.Entity.Internal.InternalContext.ExecuteSqlCommand(String sql, Object[] parameters)
at System.Data.Entity.Database.ExecuteSqlCommand(String sql, Object[] parameters)
at EF5ExecuteSqlCommandBugReproduction.Program.Main(String[] args) in c:\EF5ExecuteSqlCommandBugReproduction\EF5ExecuteSqlCommandBugReproduction\Program.cs:line 26
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
我将不胜感激.如果您认为这是EF的错误,那么我将向您报告.
非常感谢
解:
将参数列表创建和ExecuteSqlCommand打包到一个内联函数中,然后重新调用它,而不是重新调用ExecuteSqlCommand.这将确保创建新的SqlParameter数组.
var dc = new SpondleWebContext(); //衍生自DbContext
Action act = () =>
{
var pa = new SqlParameter[] { new SqlParameter("@Name", SqlDbType.NVarChar) { Value = "test" } };
dc.Database.ExecuteSqlCommand("spImport @Name", pa);
};
try { act(); } catch { }
act();
解决方法:
我没有在这里安装EntityFramework,但是我非常确定ExecuteStoreCommand方法每次都会创建一个新的DbCommand对象.您要传递的参数集合不在框架内创建,而是由多个命令重用.因此,您会收到错误.
您将必须在第二次调用之前克隆参数.
标签:ado-net,entity-framework-5,c,entity-framework 来源: https://codeday.me/bug/20191127/2076166.html