数据库
首页 > 数据库> > c#-在System.Data.Entity.Database上第二次调用ExecuteSqlCommand时出错

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