Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF6重试程序抛出“;SqlParameter已包含在另一个SqlParameterCollection“中;用于SqlQuery命令_C#_Sql Server_Entity Framework_Ado.net_Entity Framework 6 - Fatal编程技术网

C# EF6重试程序抛出“;SqlParameter已包含在另一个SqlParameterCollection“中;用于SqlQuery命令

C# EF6重试程序抛出“;SqlParameter已包含在另一个SqlParameterCollection“中;用于SqlQuery命令,c#,sql-server,entity-framework,ado.net,entity-framework-6,C#,Sql Server,Entity Framework,Ado.net,Entity Framework 6,我试图使用DBExecutionStrategy重试超时的查询,但是当超时发生时,我得到错误“SqlParameter已包含在另一个SqlParameterCollection中”。我用的是EF6 我的问题是: using (var ctx = new EntityModel()) { IEnumerable<ItemResponse> items= ctx.Database.SqlQuery<ItemResponse>( "spItemLi

我试图使用DBExecutionStrategy重试超时的查询,但是当超时发生时,我得到错误“SqlParameter已包含在另一个SqlParameterCollection中”。我用的是EF6

我的问题是:

using (var ctx = new EntityModel())
{
    IEnumerable<ItemResponse> items= ctx.Database.SqlQuery<ItemResponse>(
           "spItemListGet @UserID", new SqlParameter("@UserID", UserID)
    ).ToList();
}
使用(var ctx=new EntityModel())
{
IEnumerable items=ctx.Database.SqlQuery(
“spItemListGet@UserID”,新的SqlParameter(“@UserID”,UserID)
).ToList();
}
我的执行策略:

protected override bool ShouldRetryOn(Exception ex)
{
    bool retry = false;

    SqlException sqlException = ex as SqlException;
    if (sqlException != null)
    {
        int[] errorsToRetry =
        {
            -2,     //Timeout
        };
        if (sqlException.Errors.Cast<SqlError>().Any(x => errorsToRetry.Contains(x.Number)))
        {
            retry = true;
        }
        else
        {
            throw ex; //dont retry
        }
    }

    return retry;
}
protectedoverride bool ShouldRetryOn(异常示例)
{
bool retry=false;
SqlException SqlException=ex作为SqlException;
if(sqlException!=null)
{
int[]errorsToRetry=
{
-2,//超时
};
if(sqlException.Errors.Cast().Any(x=>errorsToRetry.Contains(x.Number)))
{
重试=真;
}
其他的
{
throw ex;//不要重试
}
}
返回重试;
}
堆栈跟踪:

System.ArgumentException: The SqlParameter is already contained by another SqlParameterCollection.
   at System.Data.SqlClient.SqlParameterCollection.Validate(Int32 index, Object value)
   at System.Data.SqlClient.SqlParameterCollection.AddRange(Array values)
   at System.Data.Entity.Core.Objects.ObjectContext.CreateStoreCommand(String commandText, Object[] parameters)
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryInternal[TElement](String commandText, String entitySetName, ExecutionOptions executionOptions, Object[] parameters)
   at System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass65`1.<ExecuteStoreQueryReliably>b__64()
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   at System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass65`1.<ExecuteStoreQueryReliably>b__63()
   at System.Data.Entity.Infrastructure.DbExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryReliably[TElement](String commandText, String entitySetName, ExecutionOptions executionOptions, Object[] parameters)
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQuery[TElement](String commandText, ExecutionOptions executionOptions, Object[] parameters)
   at System.Data.Entity.Internal.InternalContext.<>c__DisplayClass14`1.<ExecuteSqlQuery>b__13()
   at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
System.ArgumentException:另一个SqlParameterCollection已包含SqlParameter。
位于System.Data.SqlClient.SqlParameterCollection.Validate(Int32索引,对象值)
位于System.Data.SqlClient.SqlParameterCollection.AddRange(数组值)
位于System.Data.Entity.Core.Objects.ObjectContext.CreateStoreCommand(String commandText,Object[]参数)
位于System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryInternal[TElement](String commandText,String entitySetName,ExecutionOptions ExecutionOptions,Object[]参数)
在System.Data.Entity.Core.Objects.ObjectContext.c__DisplayClass65`1.b__64()中
在System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 Func,IDBEcutionStrategy executionStrategy,Boolean startLocalTransaction,Boolean releaseConnectionOnSuccess)
位于System.Data.Entity.Core.Objects.ObjectContext.c__uDisplayClass65`1.b__63()
在System.Data.Entity.Infrastructure.DbExecutionStrategy.Execute[TResult](Func`1操作)中
位于System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryReliably[TElement](String commandText,String entitySetName,ExecutionOptions ExecutionOptions,Object[]参数)
位于System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQuery[TElement](String commandText,ExecutionOptions ExecutionOptions,Object[]参数)
在System.Data.Entity.Internal.InternalContext.c__DisplayClass14`1.b__13()中
位于System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
在System.Linq.Enumerable.WhereSelectEnumerableInterator`2.MoveNext()中
位于System.Collections.Generic.List`1..ctor(IEnumerable`1集合)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

如何防止这种错误?Database.SqlQuery可以用于执行策略吗?

简短的回答:不,您不能这样做(如果您的命令有参数)

答案很长: 这是对这个问题的一个最起码的解释。我从图片中剥离了执行策略,并用一个循环来伪造它。此逻辑在中实现,特别是在
ExecuteStoreQueryInternalAsync
方法中。问题似乎是清理部分缺少
命令.Parameters.Clear()
调用

static void Main(string[] args)
{
    TestQuery();
}

private static void TestQuery()
{
    using (var ctx = new ProductContext())
    {
        var parameter = new SqlParameter("@ID", 1);
        var commandText = "select * from product where ProductId = @ID";

        Action a = () =>
        {
            IDbCommand command = new SqlCommand();
            command.CommandText = commandText;
            command.Parameters.Add(parameter);

            command.Connection = ctx.Database.Connection;
            if (command.Connection.State != ConnectionState.Open)
            {
                command.Connection.Open();
            }

            var reader = command.ExecuteReader();
            try
            {
                throw new Exception();
                while (reader.Read())
                {
                    var pId = reader["ProductID"];
                }
                reader.Close();
            }
            catch (Exception exc)
            {
                //for simplification, we just swallow this error, but in reality the connection error
                //would reach the IDbExecutionStrategy, and would do a retry. Instead we fake the retry
                //with a loop below
            }
            finally
            {
                reader.Dispose();

                //command.Parameters.Clear();  <--------- THIS LINE IS MISSING FROM EF
                command.Dispose();
            }
        };

        for (int i = 0; i < 2; i++) // we fake the retry with a loop now
        {
            a();
        }
    }
}
static void Main(字符串[]args)
{
TestQuery();
}
私有静态void TestQuery()
{
使用(var ctx=new ProductContext())
{
var参数=新的SqlParameter(“@ID”,1);
var commandText=“从产品中选择*,其中ProductId=@ID”;
行动a=()=>
{
IDbCommand=newsqlcommand();
command.CommandText=CommandText;
command.Parameters.Add(参数);
command.Connection=ctx.Database.Connection;
if(command.Connection.State!=ConnectionState.Open)
{
command.Connection.Open();
}
var reader=command.ExecuteReader();
尝试
{
抛出新异常();
while(reader.Read())
{
变量pId=读卡器[“产品ID”];
}
reader.Close();
}
捕获(异常exc)
{
//为了简化,我们只是接受这个错误,但实际上是连接错误
//将到达IDbExecutionStrategy,并将进行重试。相反,我们假装重试
//下面有一个循环
}
最后
{
reader.Dispose();

//command.Parameters.Clear();尝试ctx.SaveChanges()时,执行策略工作正常。有什么想法吗?这里有更多关于EF6错误的信息:嗯,很好。11天前修复了。@Tamas这似乎在EF 6.1.3中没有修复。如果用户在DbExecutionStrategy中设置了重试,并在代码中调用了dbContext.Database.ExecuteSqlCommand,他们将遇到上面列出的Sql参数异常。EF 6.2+已修复。此问题发生在ng对于使用EF 6.4.4而不使用重试的我,请参见此处: