Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
The SqlParameter is already contained by another...
Message
General information
Forum:
ASP.NET
Category:
Coding, syntax and commands
Miscellaneous
Thread ID:
01455279
Message ID:
01455506
Views:
24
>>>>>>I'v run into this problem before, and I hit it again tonight:
>>>>>>http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/80ed858a-64e3-4821-a1a3-44940fbf4e83
>>>>>>
>>>>>>How about this for a solution - In my DataAccess class, whenver I receive a DbParameters collection, simply make a local copy of
>>>>>>each parameter, place each copy into a new collection, then assign that collection to the DbCommand object?
>>>>>>
>>>>>>This way, my collection of parameter never really gets used, like this:
>>>>>>
>>>>>>
>>>>>>
>>>>>>private List<DbParameter> _CopyParameters(List<DbParameter> Parameters)
>>>>>>{
>>>>>>    List<DbParameter> RetVal = new List<DbParameter>();
>>>>>>
>>>>>>    foreach (DbParameter Param in Parameters)
>>>>>>    {
>>>>>>        DbParameter NewParam = _Factory.CreateParameter();
>>>>>>        NewParam.ParameterName = Param.ParameterName;
>>>>>>        NewParam.Value = Param.Value;
>>>>>>        NewParam.Direction = Param.Direction;
>>>>>>
>>>>>>        RetVal.Add(NewParam);
>>>>>>
>>>>>>       Parameters.Remove(Param);
>>>>>>
>>>>>>    }
>>>>>>
>>>>>>    return RetVal;
>>>>>>}
>>>>>>
>>>>>>
>>>>>>Then use it like this:
>>>>>>
>>>>>>public int ExecuteNonQuery(string Command, List<DbParameter> Parameters, CommandType CommandType)
>>>>>>{
>>>>>>    int RetVal = 0;
>>>>>>
>>>>>>    DbCommand cmd = _GetCommand(Command);
>>>>>>
>>>>>>    try
>>>>>>    {
>>>>>>        RetVal = cmd.ExecuteNonQuery();
>>>>>>    }
>>>>>>    catch (Exception e)
>>>>>>    {
>>>>>>        throw;
>>>>>>    }
>>>>>>
>>>>>>    return RetVal;
>>>>>>}
>>>>>>
>>>>>>
>>>>>>Then in _GetCommand()...
>>>>>>
>>>>>>
>>>>>>private DbCommand _GetCommand(string Command, List<DbParameter> Parameters, CommandType CmdType)
>>>>>>{
>>>>>>    _GetFactory();
>>>>>>    _GetConnection();
>>>>>>
>>>>>>    DbCommand cmd = _Factory.CreateCommand();
>>>>>>    cmd.CommandText = Command;
>>>>>>    cmd.Connection = _Connection;
>>>>>>    cmd.CommandType = CmdType;
>>>>>>
>>>>>>    if (Parameters != null)
>>>>>>    {
>>>>>>        List<DbParameter> NewParams = _CopyParameters(Parameters);
>>>>>>
>>>>>>        cmd.Parameters.Clear();
>>>>>>        cmd.CommandType = CmdType;
>>>>>>
>>>>>>        foreach (DbParameter p in NewParams)
>>>>>>        {
>>>>>>            cmd.Parameters.Add(p);
>>>>>>        }
>>>>>>    }
>>>>>>
>>>>>>    return cmd;
>>>>>>}
>>>>>>
>>>>>>
>>>>>>
>>>>>>I implemented this and it seems to work. Thoughts?
>>>>>
>>>>>Could you organise things so that the parameter are removed after the command executes - that would mean you wouldn't need a copy everytime:
public int ExecuteNonQuery(List<SqlParameter> l)
>>>>>        {
>>>>>            SqlCommand sc = new SqlCommand();
>>>>>            foreach (SqlParameter p in l){sc.Parameters.Add(p);}
>>>>>            int RetVal = sc.ExecuteNonQuery();
>>>>>            foreach (SqlParameter p in l){sc.Parameters.Remove(p);}
>>>>>            return RetVal;
>>>>>        }
>>>>
>>>>I tried your suggestion. It throws a runtime error "Collection was modified...."
>>>
>>>:-{ Oh well, it worked without the actual .ExecuteQuery()
>>>
>>>>Oh well. Nice try. Truth is, I'm not unhappy with my workaround.
>>>
>>>You still don't really need to make a copy. This should work (with all parameter properties handled):
public int ExecuteNonQuery(List<SqlParameter> l)
>>>        {
>>>            SqlCommand sc = new SqlCommand();
>>>
>>>            foreach (SqlParameter p in l)
>>>            {
>>>                sc.Parameters.Add(new SqlParameter(
>>>                    p.ParameterName,
>>>                    p.SqlDbType,
>>>                    p.Size,
>>>                    p.Direction,
>>>                    p.Precision,
>>>                    p.Scale,
>>>                    p.SourceColumn,
>>>                    p.SourceVersion,
>>>                    p.SourceColumnNullMapping,
>>>                    p.Value, p.XmlSchemaCollectionDatabase,
>>>                    p.XmlSchemaCollectionOwningSchema,
>>>                    p.XmlSchemaCollectionName));
>>>            }
>>>            return sc.ExecuteNonQuery();
>>>        }
>>
>>This is essentially doing the same thing. For each param, create a new one with the same prop values, and assign it to the cmd. The
>>only drawback in my case is that I'm using a factory and not all of the Param properties are supported. The technique I used doesn't
>>care about that.
>
>My point was that you don't need to make a copy of the whole list. Just using the existing one to feed in the new parameters is more efficient.
>NBD .....

Agreed. Thanks for your insight.
Everything makes sense in someone's mind
public class SystemCrasher :ICrashable
In addition, an integer field is not for irrational people
Previous
Reply
Map
View

Click here to load this message in the networking platform