• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
我的成长足迹
夫志当存高远
博客园    首页    新随笔    联系   管理    订阅  订阅

像NHibernate致敬-ado.net entity framework的范型DAO和open session in view实现

用ado.net 实现open session in view和范型DAO。

      最近用ado.net entity framework遇到了和NHibernate上相同的问题:

      1、open session in view如果entity的objectcontext在dao层关闭的话,在其他层访问lazy-load的属性就会出错,这都是因为上下文已经关闭的缘故,当然过早关闭上下文还会造成(1)在一次访问中多个DAO频繁的新建objectcontext造成不必要的麻烦;2、在更新或者删除时经常要为把从其他dao上下文里获取的数据附加到当前上下文这样极度繁琐的操作。(N)Hibernate做为一个老牌的orm框架通过引入open session  in view的方式避免上述问题,使得一次访问多个dao只使用一个session,而且把关闭的操作放在一次http访问的最后时间进行,也就是建个httpmodule在beginrequset事件时新建session,并在endrequest事件时提交事务并关闭,这样就可以实现透明的持久化和lzay-load。

      由于ado.net entity framework和NHibernate很相似,所以可以借鉴NHibernate的处理方式实现一个ado.net entity framework版的open session in view,代码如下。

 首先实现一个从httpcontext上下文中获取objectcontext的help类

 

EntityHelp
 1     public class EntityHelp
 2     {
 3         public static JobSnsEntities GetEntity()
 4         {
 5             JobSnsEntities entity;
 6             if (HttpContext.Current.Items["Entity"] == null)
 7             {
 8                 entity = new JobSnsEntities();
 9                 HttpContext.Current.Items.Add("Entity", entity);
10             }
11             else
12             {
13                 entity = HttpContext.Current.Items["Entity"] as JobSnsEntities;
14             }
15             return entity;
16         }
17     }

 

实现ihttpmodule

OSIVHttpModule
 1 public class OSIVHttpModule:IHttpModule
 2     {
 3         #region IHttpModule 成员
 4 
 5         public void Dispose()
 6         {
 7             throw new NotImplementedException();
 8         }
 9 
10         public void Init(HttpApplication context)
11         {
12             context.BeginRequest += new EventHandler(context_BeginRequest);
13             context.EndRequest += new EventHandler(context_EndRequest);
14         }
15 
16         void context_EndRequest(object sender, EventArgs e)
17         {
18             JobSnsEntities entity = HttpContext.Current.Items["Entity"] as JobSnsEntities;
19             if (entity != null)
20             {
21                 entity.SaveChanges();
22                 entity.Dispose();
23             }
24         }
25 
26         void context_BeginRequest(object sender, EventArgs e)
27         {
28             if (HttpContext.Current.Items["Entity"] == null)
29             {
30                 HttpContext.Current.Items.Add("Entity", new JobSnsEntities());
31             }
32         }
33 
34         #endregion
35     }

 

这样只要在dao中从help中获取objectcontext,我们进行完操作后不须显示的关闭。

 2、范型DAO

     在使用NHibernate时,范型DAO是个常用的省事技巧,将基础的crud写在范型DAO中,其他DAO只要去继承它,就可以公用一套crud方法,这在NHibernate中是很容易实现的,不过由于entity frameword比较笨拙,实现比起NHibernate要难看一些,代码如下

  1public class GenericEFDao<Context,T> where Context:ObjectContext where T : class
  2    {
  3        private Context _db = EntityHelp.GetEntity() as Context;
  4        public Context db
  5        {
  6            get { return _db; }
  7        }

  8
  9
 10        CRUD#region CRUD
 11        /**//// <summary>
 12        /// 通过id查找
 13        /// </summary>
 14        /// <param name="id"></param>
 15        /// <returns></returns>

 16        public virtual T FindById(object id)
 17        {
 18            string str = String.Format("select value t from {0} as t where t.{1}=@name",
 19                new object[] { GetClassType().Name, GetPrimaryKey().Name });
 20            ObjectQuery<T> query = db.CreateQuery<T>(str, new ObjectParameter[] { new ObjectParameter("name", id) });
 21            return query.FirstOrDefault();
 22        }

 23        /**//// <summary>
 24        /// 查找所有
 25        /// </summary>
 26        /// <returns></returns>

 27        public virtual List<T> FindAll()
 28        {
 29            ObjectQuery<T> query = db.CreateQuery<T>("[" + typeof(T).Name + "]");
 30            return query.ToList();
 31        }

 32
 33        /**//// <summary>
 34        /// 插入数据,并且提交变更
 35        /// </summary>
 36        /// <param name="item"></param>
 37        /// <returns></returns>

 38        public virtual T Save(T item)
 39        {
 40            return Save(item, true);
 41        }

 42
 43        /**//// <summary>
 44        /// 插入数据
 45        /// </summary>
 46        /// <param name="item"></param>
 47        /// <param name="submitChanges">是否提交变更</param>
 48        /// <returns></returns>

 49        public virtual T Save(T item, bool submitChanges)
 50        {
 51            db.AddObject(typeof(T).Name, item);
 52            if (submitChanges)
 53                db.SaveChanges();
 54            return item;
 55        }

 56        /**//// <summary>
 57        /// 删除数据,默认提交
 58        /// </summary>
 59        /// <param name="item"></param>

 60        public virtual void Delete(T item)
 61        {
 62            Delete(item, true);
 63        }

 64        /**//// <summary>
 65        /// 删除数据
 66        /// </summary>
 67        /// <param name="item"></param>
 68        /// <param name="submitChanges">是否提交</param>

 69        public virtual void Delete(T item, bool submitChanges)
 70        {
 71            db.DeleteObject(item);
 72            if (submitChanges)
 73                db.SaveChanges();
 74        }

 75        /**//// <summary>
 76        /// 更新
 77        /// </summary>

 78        public virtual void UpdateChanges()
 79        {
 80            db.SaveChanges();
 81        }

 82
 83        #endregion

 84        
 85        help#region help
 86        /**//// <summary>
 87        /// 获取主键
 88        /// </summary>
 89        /// <returns></returns>

 90        private PropertyInfo GetPrimaryKey()
 91        {
 92            PropertyInfo primaryKey = null;
 93            foreach (var a in GetClassType().GetProperties())
 94            {
 95                foreach (EdmScalarPropertyAttribute c in a.GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false))
 96                {
 97                    if (c.EntityKeyProperty)
 98                    {
 99                        primaryKey = a;
100                    }

101                }

102
103            }

104            return primaryKey;
105        }

106        /**//// <summary>
107        /// 获取type
108        /// </summary>
109        /// <returns></returns>

110        private Type GetClassType()
111        {
112            return typeof(T);
113        }

114        #endregion

 

     由于entity framework和NHibernate的相似性,我们可以把NHibernate中的最佳实践嫁接过来,使得在使用ado.net entity framework能够得心应手,不过由于项目还没完成,对于这样使用是否会发生 淮橘为枳的问题现在还是未可知的,只有等到系统上线的时候才能知道。

posted @ 2008-12-03 19:48  bwbwbw1984  阅读(1545)  评论(3)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3