2011-07-26 100 views
6

是否SqlCommand.Clone()创建深层复制或浅层副本?另外,从多个线程同时调用Clone()是否安全(创建一个多线程可以复制,设置参数值并执行的命令)?SqlCommand.Clone()是否创建深层副本或浅层副本?

+0

有关克隆,深浅拷贝和示例的更多信息,请参见[Object.MemberwiseClone](http://msdn.microsoft.com/zh-cn/library/system.object.memberwiseclone.aspx)方法http://stackoverflow.com/questions/699210/why-should-i-implement-icloneable-in-c/4186747#4186747 – Sreekumar

+0

我的问题的原因是,如果它是从多线程的Clone()SqlCommand线程安全同时。从讨论看来,这似乎是真的,所以即使它不是一个深层克隆,它也会克隆参数集。因此,在启动时,您可以准备一次SqlCommand,然后从多个线程并行克隆它以节省一些工作。 – yzorg

回答

2

从多线程调用Clone是不安全的,因为SqlCommand类本身不是线程安全类。你应该lock克隆前..

但是你可以看看使用像Reflector程序SqlCommand.Clone()方法,下面是实际的代码:

public SqlCommand Clone() 
{ 
    SqlCommand command = new SqlCommand(this); 
    Bid.Trace("<sc.SqlCommand.Clone|API> %d#, clone=%d#\n", this.ObjectID, command.ObjectID); 
    return command; 
} 

internal static void Trace(string fmtPrintfW, int a1, int a2) 
{ 
    if (((modFlags & ApiGroup.Trace) != ApiGroup.Off) && (modID != NoData)) 
    { 
     NativeMethods.Trace(modID, UIntPtr.Zero, UIntPtr.Zero, fmtPrintfW, a1, a2); 
    } 
} 

[DllImport("System.Data.dll", EntryPoint="DllBidTraceCW", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Unicode)] 
internal static extern void Trace(IntPtr hID, UIntPtr src, UIntPtr info, string fmtPrintfW, int a1, int a2); 

private SqlCommand(SqlCommand from) : this() 
{ 
    this.CommandText = from.CommandText; 
    this.CommandTimeout = from.CommandTimeout; 
    this.CommandType = from.CommandType; 
    this.Connection = from.Connection; 
    this.DesignTimeVisible = from.DesignTimeVisible; 
    this.Transaction = from.Transaction; 
    this.UpdatedRowSource = from.UpdatedRowSource; 
    SqlParameterCollection parameters = this.Parameters; 
    foreach (object obj2 in from.Parameters) 
    { 
     parameters.Add((obj2 is ICloneable) ? (obj2 as ICloneable).Clone() : obj2); 
    } 
} 

你可以看到,它创建一个新的实例,并添加到它旧版本的所有属性,但它并不深拷贝所有属性“例如Connection”,因此它是浅拷贝。

+0

我不指望它克隆SqlConnection等critcal资源。我会说,因为它克隆了ICloneable的所有参数,它正在执行深度复制的“最佳尝试”。在应用程序中,我正在审查它从不使用'原始'SqlCommand,因此Connection和Transaction属性在'from'或'original'实例上始终为null。 – yzorg

+0

@yzorg:对,但是因为它不能深入地克隆所有数据,比如'SqlConnection','Parameters' ..“,它被认为是一个浅拷贝。如果它深度复制所有数据,它只考虑“深层复制”,因此如果从原始或副本中更改任何属性,则不会影响另一个属性。 –

2

SqlCommand.Clone方法执行浅拷贝。任何属于引用类型的属性都将在两个SqlCommand实例中表示相同的对象。所以,不是线程安全的。 AFAIK,.NET框架中的所有Clone()(MemberwiseClone)方法都是浅拷贝。

您还没有发布您的代码,但我建议您创建一个新的SqlCommand而不是克隆。