2011-07-26 5 views
6

SqlCommand.Clone()은 딥 복사본 또는 얕은 복사본을 만듭니 까? 또한 Clone()을 여러 스레드에서 동시에 호출하는 것이 안전합니까? (여러 스레드가 복사하여 매개 변수 값을 설정하고 실행할 수있는 하나의 명령을 작성하십시오)?SqlCommand.Clone()은 전체 복사본이나 얕은 복사본을 만듭니 까?

+0

복제, 심층 복제와 예제 복제 및 예제에 대한 자세한 내용은 [Object.MemberwiseClone] (http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx) 메서드를 참조하십시오. http://stackoverflow.com/questionions/699210/why-should-i-implement-icloneable-in-c/4186747#4186747 – Sreekumar

+0

내 질문에 대한 이유는 여러 스레드에서 Clone() SqlCommand에 threadsafe면 같은 시간. 토론에서 그것은 진실한 것처럼 보이므로 깊은 복제가 아니더라도 매개 변수 집합을 복제합니다. 따라서 시작시 SqlCommand를 한 번 준비한 다음 나중에 병렬로 여러 스레드에서 복제하여 작업을 절약 할 수 있습니다. – yzorg

답변

2

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); 
    } 
} 

당신은 그것이 새 인스턴스를 만들 것을보고 여기에 추가 할 수 있습니다 : 당신은 당신이 Reflector 같은 프로그램을 사용하여 SqlCommand.Clone() 방법을 볼 수 있습니다 그러나

는 여기에 실제 코드입니다 .. lock 복제 전에해야 예전의 모든 속성을 포함하지만 모든 속성 (예 : Connection)을 복사하지는 않습니다. 따라서 얕은 사본입니다.

+0

SqlConnection과 같은 critcal 리소스를 복제 할 것으로 기대하지 않습니다. 전체 복사본에서 '최선의 시도'를 수행하는 ICloneable 인 모든 매개 변수를 복제하기 때문에 나는 말할 것입니다. 이 응용 프로그램에서는 '원본'SqlCommand를 사용하지 않으므로 Connection 및 Transaction 속성은 항상 '보낸 사람'또는 '원래'인스턴스에서 null이됩니다. – yzorg

+0

@yzorg : 그렇습니다. 그러나 모든 데이터를 "SqlConnection", "Parameters .."와 같이 깊이 복제하지 않기 때문에 얕은 복사본으로 간주됩니다. 모든 데이터를 깊이 복사하는 경우에만 '딥 복사'로 간주되므로 원래 또는 복사본에서 속성을 변경하면 다른 속성에 영향을주지 않습니다. –

2

SqlCommand.Clone 메서드는 얕은 복사본을 수행합니다. 참조 유형 인 모든 속성은 두 SqlCommand 인스턴스에서 동일한 개체를 나타냅니다. 따라서 스레드로부터 안전하지 않습니다.

AFAIK, .NET Framework의 모든 Clone() (MemberwiseClone) 메서드는 얕은 복사본입니다.

코드를 게시하지 않았지만 복제가 아닌 새로운 SqlCommand을 만드는 것이 좋습니다.

관련 문제