2011-07-26 92 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而不是克隆。