zoukankan      html  css  js  c++  java
  • 基于LINQ TO SQL的多层架构中,如何将实体附加至不同的DataContext

    基于LINQ TO SQL的多层架构中,如何将实体附加至不同的DataContext

    最近更新: 2013-2-19    124 0

    注意:

    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> expression)
    {
        dal.GetModel(expression);
    }
       public void Update(LinqToSqlProvider.User entity)
       {
          dal.Update(entity);
       }
    }
    class DAL
    {

             public LinqToSqlProvider.User GetModel (Expression> 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这样的属性,由于我们在获取实体时并未将这些关联的内容一起读出 来,而在附加时(Attach)这些属性便会出现ObjectDisposedException异常,也就是因为之前查询这个 实体时的DataContext已经释放掉了导致的。

    解决方法:

    /// 


             /// 辅助LinqToSql实体与原DataContext分离
             /// 

             /// 
             /// 
             public static void Detatch(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中去

  • 相关阅读:
    3.css中的颜色
    5.html5中的路径表示
    4.html5中超链接
    3.html5的文本元素
    2.html5的基本格式
    1.html5究竟是什么
    2.css选择器
    C++11--智能指针shared_ptr,weak_ptr,unique_ptr <memory>
    C++11--编译器生成的函数
    C++11--右值引用(Perfect Forwarding)
  • 原文地址:https://www.cnblogs.com/wahaccp/p/3233064.html
Copyright © 2011-2022 走看看