准备抽象NHibernate和EntityFramework
准备抽象NHibernate和EntityFramework
背景
考虑到目前中小企业应用的主流是ORM,我准备在NHibernate和EntityFramework之间找到一个抽象层,也就是说我准备只支持NHibernate和EntityFramework。
思路
NH和EF都实现了“工作单元”和“主键映射”这两种企业应用模式,而这两种模式其实就是管理一种状态机,如下图:
实现
工作单元接口
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Happy.Domain
8 {
9 /// <summary>
10 /// 工作单元接口。
11 /// </summary>
12 /// <remarks>
13 /// 聚合状态:
14 /// <list type="number">
15 /// <item> transient:实例存在于内存中,但不存在于工作单元和数据库中。 </item>
16 /// <item> persistent in database:实例存在于数据库中。 </item>
17 /// <item> persistent in unitofwork:实例存在于工作单元中。 </item>
18 /// <item> detached:实例存在于内存和数据库中,但不存在于工作单元中。 </item>
19 /// </list>
20 /// 合法转换:
21 /// <list type="number">
22 /// <item> transient > Save -> persistent in unitofwork,Flush时会生成Insert Sql,场景:从UI层创建实例,执行创建。 </item>
23 /// <item> detached -> Update -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,执行修改(支持离线乐观并发)。 </item>
24 /// <item> detached -> Persist -> persistent in unitofwork,Flush时不会生成Sql,场景:将实例从另一个工作单元脱钩,添加到当前工作单元。 </item>
25 /// <item> detached -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从UI层重建实例,删除记录。 </item>
26 /// <item> detached -> Merge -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,合并到从数据库重建的实例,执行修改(不支持离线乐观并发)。 </item>
27 /// <item> persistent in unitofwork -> Evict -> detached,Flush时不会生成Sql,场景:将实例从当前工作单元脱钩,添加到另一个工作单元。 </item>
28 /// <item> persistent in unitofwork -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从数据库重建实例,删除记录。 </item>
29 /// <item> persistent in unitofwork -> Flush -> persistent in database,提交工作单元,会生成SQL,场景:执行完一系列Create、Update和Delete后统一提交,只产生一次数据库往返。 </item>
30 /// <item> persistent in database -> Load -> persistent in unitofwork,从数据库重建实例。 </item>
31 /// <item> persistent in database -> Refresh -> persistent in unitofwork,从数据库刷新实例,场景:使用存储过程修改了一个实例,使用此方法重新刷新一下。 </item>
32 /// </list>
33 /// </remarks>
34 public interface IUnitOfWork : IDisposable
35 {
36 /// <summary>
37 /// 判断 <paramref name="item"/> 是否 persistent in unitofwork。
38 /// </summary>
39 bool Contains<TAggregateRoot> (TAggregateRoot item)
40 where TAggregateRoot : AggregateRoot;
41
42 /// <summary>
43 /// transient > Save -> persistent in unitofwork,Flush时会生成Insert Sql,场景:从UI层创建实例,执行创建。
44 /// </summary>
45 void Save<TAggregateRoot> (TAggregateRoot item)
46 where TAggregateRoot : AggregateRoot;
47
48 /// <summary>
49 /// detached -> Update -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,执行修改(支持离线乐观并发)。
50 /// </summary>
51 void Update<TAggregateRoot> (TAggregateRoot item)
52 where TAggregateRoot : AggregateRoot;
53
54 /// <summary>
55 /// detached -> Persist -> persistent in unitofwork,Flush时不会生成Sql,场景:将实例从另一个工作单元脱钩,添加到当前工作单元。
56 /// </summary>
57 void Persist<TAggregateRoot> (TAggregateRoot item)
58 where TAggregateRoot : AggregateRoot;
59
60 /// <summary>
61 /// 执行如下两种转换:
62 /// <list type="number">
63 /// <item> detached -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从UI层重建实例,删除记录。 </item>
64 /// <item> persistent in unitofwork -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从数据库重建实例,删除记录。 </item>
65 /// </list>
66 /// </summary>
67 void Delete<TAggregateRoot> (TAggregateRoot item)
68 where TAggregateRoot : AggregateRoot;
69
70 /// <summary>
71 /// detached -> Merge -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,合并到从数据库重建的实例,执行修改(不支持离线乐观并发)。
72 /// </summary>
73 void Merge<TAggregateRoot> (TAggregateRoot item)
74 where TAggregateRoot : AggregateRoot;
75
76 /// <summary>
77 /// persistent in unitofwork -> Evict -> detached,Flush时不会生成Sql,场景:将实例从当前工作单元脱钩,添加到另一个工作单元。
78 /// </summary>
79 void Evict<TAggregateRoot> (TAggregateRoot item)
80 where TAggregateRoot : AggregateRoot;
81
82 /// <summary>
83 /// persistent in unitofwork -> Flush -> persistent in database,提交工作单元,会生成SQL,场景:执行完一系列Create、Update和Delete后统一提交,只产生一次数据库往返。
84 /// </summary>
85 void Flush();
86
87 /// <summary>
88 /// persistent in database -> Load -> persistent in unitofwork,从数据库重建实例。
89 /// </summary>
90 TAggregateRoot Load<TAggregateRoot> (Guid id)
91 where TAggregateRoot : AggregateRoot;
92
93 /// <summary>
94 /// persistent in database -> Refresh -> persistent in unitofwork,从数据库刷新实例,场景:使用存储过程修改了一个实例,使用此方法重新刷新一下。
95 /// </summary>
96 void Refresh<TAggregateRoot> (TAggregateRoot item)
97 where TAggregateRoot : AggregateRoot;
98
99 /// <summary>
100 /// 回滚所有自上次提交以后的修改。
101 /// </summary>
102 void Clear();
103
104 /// <summary>
105 /// 清空处于persistent in unitofwork状态的实例。
106 /// </summary>
107 TRepository GetRepository<TRepository> ()
108 where TRepository : IRepository;
109 }
110 }
基于EntityFramework的工作单元
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using System.Data;
7 using System.Data.Entity;
8 using System.Data.Entity.Infrastructure;
9
10 using Microsoft.Practices.ServiceLocation;
11
12 using Happy.Domain;
13 using Happy.DesignByContract;
14
15 namespace Happy.EntityFramework
16 {
17 /// <summary>
18 /// 基于EntityFramework的工作单元。
19 /// </summary>
20 public abstract class UnitOfWork : DbContext, IUnitOfWork
21 {
22 private readonly Dictionary<Type, IRepository> repositories = new Dictionary<Type, IRepository> ();
23
24 /// <summary>
25 /// 构造方法。
26 /// </summary>
27 protected UnitOfWork()
28 {
29 }
30
31 /// <summary>
32 /// 构造方法。
33 /// </summary>
34 protected UnitOfWork( string nameOrConnectionString)
35 : base (nameOrConnectionString)
36 {
37 }
38
39 /// <inheritdoc />
40 public bool Contains<TAggregateRoot> (TAggregateRoot item)
41 where TAggregateRoot : AggregateRoot
42 {
43 item.MustNotNull( " item " );
44
45 return this .Entry(item).State != EntityState.Detached;
46 }
47
48 /// <inheritdoc />
49 public void Save<TAggregateRoot> (TAggregateRoot item)
50 where TAggregateRoot : AggregateRoot
51 {
52 item.MustNotNull( " item " );
53
54 this .Set<TAggregateRoot> ().Add(item);
55 }
56
57 /// <inheritdoc />
58 public void Update<TAggregateRoot> (TAggregateRoot item)
59 where TAggregateRoot : AggregateRoot
60 {
61 item.MustNotNull( " item " );
62
63 this .Entry(item).State = EntityState.Modified;
64 }
65
66 /// <inheritdoc />
67 public void Persist<TAggregateRoot> (TAggregateRoot item)
68 where TAggregateRoot : AggregateRoot
69 {
70 item.MustNotNull( " item " );
71
72 this .Entry(item).State = EntityState.Unchanged;
73 }
74
75 /// <inheritdoc />
76 public void Delete<TAggregateRoot> (TAggregateRoot item)
77 where TAggregateRoot : AggregateRoot
78 {
79 item.MustNotNull( " item " );
80
81 this .Entry(item).State = EntityState.Deleted;
82 }
83
84 /// <inheritdoc />
85 public void Merge<TAggregateRoot> (TAggregateRoot item)
86 where TAggregateRoot : AggregateRoot
87 {
88 item.MustNotNull( " item " );
89
90 var persistItem = this .Set<TAggregateRoot> ().Find(item.Id);
91
92 this .Entry(persistItem).CurrentValues.SetValues(item);
93 }
94
95 /// <inheritdoc />
96 public void Evict<TAggregateRoot> (TAggregateRoot item)
97 where TAggregateRoot : AggregateRoot
98 {
99 item.MustNotNull( " item " );
100
101 this .Entry(item).State = EntityState.Detached;
102 }
103
104 /// <inheritdoc />
105 public void Flush()
106 {
107 try
108 {
109 base .SaveChanges();
110 }
111 catch (DbUpdateConcurrencyException ex)
112 {
113 throw new OptimisticConcurrencyException(ex.Message, ex);
114 }
115 }
116
117 public TAggregateRoot Load<TAggregateRoot> (Guid id)
118 where TAggregateRoot : AggregateRoot
119 {
120 return this .Set<TAggregateRoot> ().Find(id);
121 }
122
123 public void Refresh<TAggregateRoot> (TAggregateRoot item)
124 where TAggregateRoot : AggregateRoot
125 {
126 item.MustNotNull( " item " );
127
128 this .Entry(item).Reload();
129 }
130
131 /// <inheritdoc />
132 public void Clear()
133 {
134 base .ChangeTracker.Entries()
135 .ToList()
136 .ForEach(entry => entry.State = System.Data.EntityState.Detached);
137 }
138
139 /// <inheritdoc />
140 public TRepository GetRepository<TRepository> ()
141 where TRepository : IRepository
142 {
143 var key = typeof (TRepository);
144
145 if (! repositories.ContainsKey(key))
146 {
147 var repository = ServiceLocator.Current.GetInstance<TRepository> ();
148 (repository as IEntityFrameworkRepository).Owner = this ;
149 repositories[key] = repository;
150 }
151
152 return (TRepository)repositories[key];
153 }
154 }
155 }
备注
其实我们经常忽略一个关于接口的问题,就是异常本身也是API的一部分,虽然这部分在C#中没有办法显式的表达,等我的朋友实现完了NH版本的工作单元的开发,我们就继续对异常进行抽象。
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于准备抽象NHibernate和EntityFramework的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did45522