2011-07-26 29 views
6

SqlCommand.Clone() tạo bản sao sâu hoặc bản sao nông không? Ngoài ra, có an toàn khi gọi Clone() từ nhiều luồng cùng lúc (tạo một lệnh mà nhiều luồng có thể sao chép, đặt giá trị tham số và thực thi) không?SqlCommand.Clone() có tạo bản sao sâu hoặc bản sao nông không?

+0

Để biết thêm thông tin về nhân bản, bản sao sâu so với nông và ví dụ, hãy xem phương pháp [Object.MemberwiseClone] (http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx) http://stackoverflow.com/questions/699210/why-should-i-implement-icloneable-in-c/4186747#4186747 – Sreekumar

+0

Lý do cho câu hỏi của tôi là nếu nó là threadsafe để Clone() SqlCommand từ nhiều chủ đề tại cùng một lúc. Từ các cuộc thảo luận có vẻ như đó là sự thật, vì vậy mặc dù nó không phải là một bản sao sâu, nó clone tập hợp tham số. Vì vậy, lúc khởi động, bạn có thể chuẩn bị SqlCommand một lần, sau đó sao chép nó từ nhiều luồng song song để lưu một số công việc. – yzorg

Trả lời

2

Không an toàn khi gọi Clone từ nhiều chủ đề vì chính lớp học SqlCommand không phải là lớp an toàn chủ đề. bạn nên lock trước khi nhân bản ..

Tuy nhiên bạn có thể nhìn vào SqlCommand.Clone() phương pháp sử dụng các chương trình như Reflector, đây là mã thực tế:

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

Bạn có thể thấy rằng nó tạo một đối tượng mới và thêm vào đó tất cả các thuộc tính cũ, nhưng nó không sao chép sâu tất cả các thuộc tính "chẳng hạn như Connection chẳng hạn" và do đó nó là bản sao nông.

+0

Tôi không mong đợi nó sao chép tài nguyên critcal như SqlConnection. Tôi sẽ nói bởi vì nó nhân bản tất cả các tham số ICloneable rằng nó đang thực hiện một 'nỗ lực tốt nhất' tại một bản sao sâu. Trong ứng dụng tôi đang xem xét nó không bao giờ sử dụng SqlCommand 'ban đầu', vì vậy các thuộc tính Connection và Transaction sẽ luôn luôn là null trên thể hiện 'from' hoặc 'original'. – yzorg

+0

@yzorg: đúng, nhưng vì nó không sao chép tất cả dữ liệu sâu sắc "như' SqlConnection', 'Tham số' ..", nó được coi là bản sao nông. Nó chỉ được coi là một 'bản sao sâu' nếu nó sao chép tất cả dữ liệu sâu sắc, vì vậy nếu bạn thay đổi bất kỳ tài sản nào từ bản gốc hoặc bản sao, nó sẽ không ảnh hưởng đến tài sản khác. –

2

Phương thức SqlCommand.Clone thực hiện bản sao nông. Bất kỳ thuộc tính nào là một kiểu tham chiếu sẽ đại diện cho cùng một đối tượng trong cả hai trường hợp SqlCommand. Vì vậy, không phải thread an toàn.

AFAIK, tất cả các phương thức Clone() (MemberwiseClone) trong khuôn khổ .NET là bản sao nông.

Bạn chưa đăng mã, nhưng tôi khuyên bạn nên tạo SqlCommand mới thay vì nhân bản.

Các vấn đề liên quan