最近用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类
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
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
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
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要难看一些,代码如下
1
public class GenericEFDao<Context,T> where Context:ObjectContext where T : class
2![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
private Context _db = EntityHelp.GetEntity() as Context;
4
public Context db
5![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
6![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _db; }
7
}
8![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
CRUD#region CRUD
11![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
12
/// 通过id查找
13
/// </summary>
14
/// <param name="id"></param>
15
/// <returns></returns>
16
public virtual T FindById(object id)
17![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
18
string str = String.Format("select value t from {0} as t where t.{1}=@name",
19![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
new object[]
{ GetClassType().Name, GetPrimaryKey().Name });
20![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
ObjectQuery<T> query = db.CreateQuery<T>(str, new ObjectParameter[]
{ new ObjectParameter("name", id) });
21
return query.FirstOrDefault();
22
}
23![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
24
/// 查找所有
25
/// </summary>
26
/// <returns></returns>
27
public virtual List<T> FindAll()
28![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
29
ObjectQuery<T> query = db.CreateQuery<T>("[" + typeof(T).Name + "]");
30
return query.ToList();
31
}
32![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
34
/// 插入数据,并且提交变更
35
/// </summary>
36
/// <param name="item"></param>
37
/// <returns></returns>
38
public virtual T Save(T item)
39![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
40
return Save(item, true);
41
}
42![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
43![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <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![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
51
db.AddObject(typeof(T).Name, item);
52
if (submitChanges)
53
db.SaveChanges();
54
return item;
55
}
56![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
57
/// 删除数据,默认提交
58
/// </summary>
59
/// <param name="item"></param>
60
public virtual void Delete(T item)
61![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
62
Delete(item, true);
63
}
64![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
65
/// 删除数据
66
/// </summary>
67
/// <param name="item"></param>
68
/// <param name="submitChanges">是否提交</param>
69
public virtual void Delete(T item, bool submitChanges)
70![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
71
db.DeleteObject(item);
72
if (submitChanges)
73
db.SaveChanges();
74
}
75![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
76
/// 更新
77
/// </summary>
78
public virtual void UpdateChanges()
79![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
80
db.SaveChanges();
81
}
82![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
83
#endregion
84
85![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
help#region help
86![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
87
/// 获取主键
88
/// </summary>
89
/// <returns></returns>
90
private PropertyInfo GetPrimaryKey()
91![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
92
PropertyInfo primaryKey = null;
93
foreach (var a in GetClassType().GetProperties())
94![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
95
foreach (EdmScalarPropertyAttribute c in a.GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false))
96![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
97
if (c.EntityKeyProperty)
98![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
99
primaryKey = a;
100
}
101
}
102![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
103
}
104
return primaryKey;
105
}
106![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
107
/// 获取type
108
/// </summary>
109
/// <returns></returns>
110
private Type GetClassType()
111![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
112
return typeof(T);
113
}
114
#endregion
由于entity framework和NHibernate的相似性,我们可以把NHibernate中的最佳实践嫁接过来,使得在使用ado.net entity framework能够得心应手,不过由于项目还没完成,对于这样使用是否会发生 淮橘为枳的问题现在还是未可知的,只有等到系统上线的时候才能知道。