SqlCommand.Clone() 是创建深拷贝还是浅拷贝?
Posted
技术标签:
【中文标题】SqlCommand.Clone() 是创建深拷贝还是浅拷贝?【英文标题】:Does SqlCommand.Clone() create a deep copy or shallow copy? 【发布时间】:2011-10-13 02:36:17 【问题描述】:SqlCommand.Clone()
是创建深拷贝还是浅拷贝?另外,从多个线程并发调用Clone()
是否安全(创建一个多个线程可以复制、设置参数值和执行的命令)?
【问题讨论】:
有关克隆、深拷贝和浅拷贝以及示例的更多信息,请参阅Object.MemberwiseClone 方法***.com/questions/699210/… 我的问题的原因是它是否是同时来自多个线程的 Clone() SqlCommand 线程安全的。从讨论来看,这似乎是正确的,因此即使它不是深度克隆,它也确实克隆了参数集。因此,在启动时,您可以准备一次 SqlCommand,然后从多个并行线程中克隆它以节省一些工作。 【参考方案1】:从多个线程调用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
”,因此它是浅拷贝。
【讨论】:
我不希望它克隆像 SqlConnection 这样的关键资源。我会说,因为它克隆了所有 ICloneable 参数,因此它在深层副本中执行了“最佳尝试”。在我正在审查的应用程序中,它从不使用“原始”SqlCommand,因此“来自”或“原始”实例的连接和事务属性将始终为空。 @yzorg:是的,但是因为它不会像SqlConnection
、Parameters
..那样深度克隆所有数据,所以它被认为是浅拷贝。如果它深度复制所有数据,它只会考虑deep copy
,因此如果您更改原始或副本的任何属性,无论如何它都不会影响另一个。【参考方案2】:
SqlCommand.Clone
方法执行浅拷贝。任何作为引用类型的属性都将在两个 SqlCommand 实例中表示相同的对象。所以,不是线程安全的。
AFAIK,.NET 框架中的所有 Clone() (MemberwiseClone) 方法都是浅拷贝。
您尚未发布您的代码,但我建议您创建一个新的 SqlCommand
而不是克隆。
【讨论】:
以上是关于SqlCommand.Clone() 是创建深拷贝还是浅拷贝?的主要内容,如果未能解决你的问题,请参考以下文章
React 是在内部创建 prevState 的深拷贝还是浅拷贝?