程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 基於LINQ TO SQL的多層架構中,如何將實體附加至不同的DataContext

基於LINQ TO SQL的多層架構中,如何將實體附加至不同的DataContext

編輯:關於.NET

注意:

1.本文中所提到的“實體”均為由LINQ TO SQL生成的(即.dbml)

2.你需要了解LINQ TO SQL對表關聯的實現方式,EntitySet 和 EntityRef

也許你看到標題後,會覺得問題比較抽象,那麼我舉個實例來具體說明一下問題。

在基於LINQ TO SQL的N層架構中,假如我們需要對一個實體進行更新,那麼流程應是這樣:

流程

BLL.GetModel(p=>p.id==1) --> 修改相應屬性(字段)值 --> BLL.Update(Entity entity) --> DAL.Update(Entity entity) --> 更新成功

此時,我們需要將這個實體從業務層(BLL)傳遞到數據訪問層(DAL),當GetModel方法返回實體後 會立即釋放掉DataContext,然後到了執行DAL.Update(Entity entity)方法時又重新實例化一個 DataContext來進行更新操作;可見被傳遞的實體是從第一個DataContext傳遞到另一個 DataContext,在 LINQ TO SQL中這種跨越不同DataContext操作時,需要先進行附加操作,也就是 context.Entity.Attach(entity,true); 最後再context.SubmitChanges();

還是看看代碼吧:

class BLL
{
   private readonly DAL dal = new DAL();
   public LinqToSqlProvider.User GetModel (Expression<Func<LinqToSqlProvider.User, bool>> expression)
{
    dal.GetModel(expression);
}
   public void Update(LinqToSqlProvider.User entity)
   {
      dal.Update(entity);
   }
}
class DAL
{

         public LinqToSqlProvider.User GetModel (Expression<Func<LinqToSqlProvider.User, bool>> expression)
         {
             LinqToSqlProvider.User entry = new  CriTextBroadcast.LinqToSqlProvider.User();
             using (CriTextBroadcastDBDataContext context = DataContext)
             {
                 entry =  context.User.SingleOrDefault(expression);
             }
             return entry;
         }
         public void Update(LinqToSqlProvider.User entity)
         {
            using (CriTextBroadcastDBDataContext context = DataContext)
             {
                 context.User.Attach(entry, true);
                 context.SubmitChanges();
             }
         }
}

實際我們用以上代碼操作時,會出現此異常:

已嘗試 Attach 或 Add 實體,該實體不是新實體,可能是從其他 DataContext 中加載來 的......

查了N多資料未果,後來還是在一國外的帖子裡看到了類似問題。原來是這個實體對應的表有若干個關 聯表,如:User -> Message ,User -> Images等,在生成實體類時會自動產生: EntitySet<Message> Message這樣的屬性,由於我們在獲取實體時並未將這些關聯的內容一起讀出 來,而在附加時(Attach)這些屬性便會出現ObjectDisposedException異常,也就是因為之前查詢這個 實體時的DataContext已經釋放掉了導致的。

解決方法:

/// <summary>
         /// 輔助LinqToSql實體與原DataContext分離
         /// </summary>
         /// <typeparam name="TEntity"></typeparam>
         /// <param name="entity"></param>
         public static void Detatch<TEntity>(TEntity entity)
         {
             Type t = entity.GetType();
             System.Reflection.PropertyInfo[] properties = t.GetProperties (System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
             foreach (var property in properties)
             {
                 string name = property.Name;
                 if (property.PropertyType.IsGenericType &&
                 property.PropertyType.GetGenericTypeDefinition() ==  typeof(EntitySet<>))
                 {
                     property.SetValue(entity, null, null);
                 }
             }
             System.Reflection.FieldInfo[] fields = t.GetFields (System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
             foreach (var field in fields)
             {
                 string name = field.Name;
                 if (field.FieldType.IsGenericType &&
                 field.FieldType.GetGenericTypeDefinition() == typeof (EntityRef<>))
                 {
                     field.SetValue(entity, null);
                 }
             }
             System.Reflection.EventInfo eventPropertyChanged = t.GetEvent ("PropertyChanged");
             System.Reflection.EventInfo eventPropertyChanging =  t.GetEvent("PropertyChanging");
             if (eventPropertyChanged != null)
             {
                 eventPropertyChanged.RemoveEventHandler(entity,  null);
             }
             if (eventPropertyChanging != null)
             {
                 eventPropertyChanging.RemoveEventHandler(entity,  null);
             }
         }

應在獲得實體後使用Detach(entity)方法將實體與原DataContext分離,然後再附加(Attach)到新的 DataContext中去

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved