如何从DataContext的跟踪机制中分离LINQ-to-SQL数据对象?

在询问了这个问题之后 ,我被告知Table.Attach()方法是如何工作的,我还有另外一个问题。

如何从DataContext的状态跟踪机制中分离LINQ-to-SQL数据对象? 基本上,我想拉一条记录并更改记录上的数据。 但是,当我在同一个DataContext实例上调用SubmitChanges()时,除非我明确调用Attach()否则我不希望更新记录。 这是如何完成的?

从此站点解释如何分离linq对象将此方法添加到要分离的对象:

 public void Detach() { GetType().GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, null); } 

我强烈建议您如果要使用LINQ to SQL, 则应更改设计以适应LINQ to SQL在所有附加修改实体上提交更改的行为 。 根据我的经验,尝试解决此function只会导致痛苦。

遗憾的是,如果不对实体进行序列化和反序列化,则无法从以前的DataContext中显式分离实体。

您可以为您的目的做的是创建从数据库中提取出来的对象的副本并使用该副本。 在这种情况下,您的原始对象不会受到影响。 当需要更新数据库时,您只需将副本附加到DataContext即可。

我克隆了使用Serialize / Deserialize从DataContext查询的对象,并将新对象提交给同一个DataContext而没有任何问题。 如果有任何附加实体,则需要在提交克隆之前使用ID重新获取它们。

 /// Used for serializing and de-serializing objects. public static class Serializer { /// Clones an object. /// The type of object to be cloned. /// The object to be cloned. /// A clone of the specified object. public static T Clone(T source) { return Deserialize(Serialize(source)); } /// Serializes an object as an XML string. /// A System.Object representing the object to be serialized. /// A System.String representing an XML representation of the specified object. public static string Serialize(object value) { if (value.GetType() == typeof(string)) { return value.ToString(); } StringWriter stringWriter = new StringWriter(); using (XmlWriter writer = XmlWriter.Create(stringWriter)) { DataContractSerializer serializer = new DataContractSerializer(value.GetType()); serializer.WriteObject(writer, value); } return stringWriter.ToString(); } /// Creates an object from an XML representation of the object. /// The type of object to be created. /// A System.String representing an XML representation of an object. /// A new object. public static T Deserialize(string serializedValue) { Type type = typeof(T); using (StringReader stringReader = new StringReader(serializedValue)) { using (XmlReader reader = XmlReader.Create(stringReader)) { DataContractSerializer serializer = new DataContractSerializer(type); object deserializedValue = serializer.ReadObject(reader); return (T)deserializedValue; } } } } 

在许多情况下,最简单的解决方案是序列化/反序列化对象以便轻松克隆它。 您使用哪种序列化/克隆方法取决于您。 这个问题在这方面有很多建议。

我喜欢使用Newtonsoft JSON.NET进行序列化,因为它非常易于使用,具有最低要求(例如,不需要编译器属性),并且我已经将它用于我项目中的其他内容。 根据您的使用情况(例如,分离要在UI模型中使用的LINQ / SQL实体),您可能希望擦除数据库ID。 一种简单的方法是将自定义DefaultContractResolver类传递给JSON.NET,它将排除ID属性:

  return JsonConvert.SerializeObject(oModel, new JsonSerializerSettings() { ContractResolver = new DNSConfigurationModel.DNSConfigSerializer() }); ///  /// Helper class to ensure that we do not serialize the domainAdvancedDNS child objects /// (we will create our own child collections for serialization). We also suppress serialization of the key ID's. ///  public class DNSConfigSerializer : DefaultContractResolver { protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) { IList properties = base.CreateProperties(type, memberSerialization); return (from p in properties where p.PropertyName != "DomainAdvancedDNS" && p.PropertyName != "domainAdvancedDNSSRVs" && !(p.DeclaringType.Name == "DomainAdvancedDN" && p.PropertyName == "domainAdvancedDNSConfigID") && p.PropertyName != "DomainAdvancedDNSID" && p.PropertyName != "domainAdvancedDNSSRVID" select p).ToList(); } }