近来用到了Linq2Sql的方法,遇到了一个更新问题。在此记录下来与大家分享。
废话不多说,请看:
1.数据库表结构如下:
需求很简单,一个Order表保存订单,一个OrderDetails保存订单明细。同时2个表有主外键的关系。
数据库里数据如下:
好的,是不是很简单。现在如果我们要把Order_Details表的EntryId等于3的那条记录的Qty更新成200,该怎么做呢?
Linq2Sql实现起来十分简单,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 static void Main(string[] args) 2 { 3 var item = default(Order_Detail); 4 using (var db = new ToyDataContext()) 5 { 6 item = db.GetTable().FirstOrDefault(p => p.EntryId == 3); 7 } 8 9 if (item != null)10 {11 item.Qry=100;12 using (var db=new ToyDataContext())13 {14 db.GetTable ().Attach(item);15 db.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, item);16 db.SubmitChanges();17 }18 }19 }
当当当,但是在执行的时候,却抛出如下异常
原来是这个实体对应的表有若干个关联表,在生成实体类时会自动产生:EntityRef<Order> Order这样的属性,但是Linq2Sql默认是延迟加载的,所以在Attach的时候,这些EntityRef还没有加载。
好了,于是我们想到了可以在首次从数据库查询的时候不启用延迟加载,将DeferredLoadingEnabled设置为false。这样,在执行查询时,将不会为实体加载任何需延迟查询的数据。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 static void Main(string[] args) 2 { 3 var item = default(Order_Detail); 4 using (var db = new ToyDataContext()) 5 { 6 db.DeferredLoadingEnabled = false;//不会为实体加载任何需延迟查询的数据 7 item = db.GetTable().FirstOrDefault(p => p.EntryId == 3); 8 } 9 10 if (item != null)11 {12 item.Qry = 200;13 using (var db = new ToyDataContext())14 {15 db.GetTable ().Attach(item);16 db.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, item);17 db.SubmitChanges();18 }19 }20 }
另外还可以通过手动Detach方法,手工移除关联
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 static void Main(string[] args) 2 { 3 var item = default(Order_Detail); 4 using (var db = new ToyDataContext()) 5 { 6 // db.DeferredLoadingEnabled = false;//不会为实体加载任何需延迟查询的数据 7 item = db.GetTable().FirstOrDefault(p => p.EntryId == 3); 8 } 9 10 if (item != null)11 {12 item.Qry = 200;13 using (var db = new ToyDataContext())14 {15 Detatch(item);//Detatch16 db.GetTable ().Attach(item);17 db.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, item);18 db.SubmitChanges();19 }20 }21 }22 23 public static void Detatch (TEntity entity)24 {25 Type t = entity.GetType();26 System.Reflection.PropertyInfo[] properties = t.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);27 foreach (var property in properties)28 {29 string name = property.Name;30 if (property.PropertyType.IsGenericType &&31 property.PropertyType.GetGenericTypeDefinition() == typeof(EntitySet<>))32 {33 property.SetValue(entity, null, null);34 }35 }36 System.Reflection.FieldInfo[] fields = t.GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);37 foreach (var field in fields)38 {39 string name = field.Name;40 if (field.FieldType.IsGenericType &&41 field.FieldType.GetGenericTypeDefinition() == typeof(EntityRef<>))42 {43 field.SetValue(entity, null);44 }45 }46 System.Reflection.EventInfo eventPropertyChanged = t.GetEvent("PropertyChanged");47 System.Reflection.EventInfo eventPropertyChanging = t.GetEvent("PropertyChanging");48 if (eventPropertyChanged != null)49 {50 eventPropertyChanged.RemoveEventHandler(entity, null);51 }52 if (eventPropertyChanging != null)53 {54 eventPropertyChanging.RemoveEventHandler(entity, null);55 }56 }