博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
幸福框架:准备抽象NHibernate和EntityFramework,大家给点意见
阅读量:5844 次
发布时间:2019-06-18

本文共 8520 字,大约阅读时间需要 28 分钟。

背景

考虑到目前中小企业应用的主流是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     ///  10     /// 工作单元接口。 11     ///  12     /// 
13 /// 聚合状态: 14 ///
15 ///
transient:实例存在于内存中,但不存在于工作单元和数据库中。
16 ///
persistent in database:实例存在于数据库中。
17 ///
persistent in unitofwork:实例存在于工作单元中。
18 ///
detached:实例存在于内存和数据库中,但不存在于工作单元中。
19 ///
20 /// 合法转换: 21 ///
22 ///
transient > Save -> persistent in unitofwork,Flush时会生成Insert Sql,场景:从UI层创建实例,执行创建。
23 ///
detached -> Update -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,执行修改(支持离线乐观并发)。
24 ///
detached -> Persist -> persistent in unitofwork,Flush时不会生成Sql,场景:将实例从另一个工作单元脱钩,添加到当前工作单元。
25 ///
detached -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从UI层重建实例,删除记录。
26 ///
detached -> Merge -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,合并到从数据库重建的实例,执行修改(不支持离线乐观并发)。
27 ///
persistent in unitofwork -> Evict -> detached,Flush时不会生成Sql,场景:将实例从当前工作单元脱钩,添加到另一个工作单元。
28 ///
persistent in unitofwork -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从数据库重建实例,删除记录。
29 ///
persistent in unitofwork -> Flush -> persistent in database,提交工作单元,会生成SQL,场景:执行完一系列Create、Update和Delete后统一提交,只产生一次数据库往返。
30 ///
persistent in database -> Load -> persistent in unitofwork,从数据库重建实例。
31 ///
persistent in database -> Refresh -> persistent in unitofwork,从数据库刷新实例,场景:使用存储过程修改了一个实例,使用此方法重新刷新一下。
32 ///
33 ///
34 public interface IUnitOfWork : IDisposable 35 { 36 /// 37 /// 判断
是否 persistent in unitofwork。 38 ///
39 bool Contains
(TAggregateRoot item) 40 where TAggregateRoot : AggregateRoot; 41 42 ///
43 /// transient > Save -> persistent in unitofwork,Flush时会生成Insert Sql,场景:从UI层创建实例,执行创建。 44 /// 45 void Save
(TAggregateRoot item) 46 where TAggregateRoot : AggregateRoot; 47 48 ///
49 /// detached -> Update -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,执行修改(支持离线乐观并发)。 50 /// 51 void Update
(TAggregateRoot item) 52 where TAggregateRoot : AggregateRoot; 53 54 ///
55 /// detached -> Persist -> persistent in unitofwork,Flush时不会生成Sql,场景:将实例从另一个工作单元脱钩,添加到当前工作单元。 56 /// 57 void Persist
(TAggregateRoot item) 58 where TAggregateRoot : AggregateRoot; 59 60 ///
61 /// 执行如下两种转换: 62 ///
63 ///
detached -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从UI层重建实例,删除记录。
64 ///
persistent in unitofwork -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从数据库重建实例,删除记录。
65 ///
66 ///
67 void Delete
(TAggregateRoot item) 68 where TAggregateRoot : AggregateRoot; 69 70 ///
71 /// detached -> Merge -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,合并到从数据库重建的实例,执行修改(不支持离线乐观并发)。 72 /// 73 void Merge
(TAggregateRoot item) 74 where TAggregateRoot : AggregateRoot; 75 76 ///
77 /// persistent in unitofwork -> Evict -> detached,Flush时不会生成Sql,场景:将实例从当前工作单元脱钩,添加到另一个工作单元。 78 /// 79 void Evict
(TAggregateRoot item) 80 where TAggregateRoot : AggregateRoot; 81 82 ///
83 /// persistent in unitofwork -> Flush -> persistent in database,提交工作单元,会生成SQL,场景:执行完一系列Create、Update和Delete后统一提交,只产生一次数据库往返。 84 /// 85 void Flush(); 86 87 ///
88 /// persistent in database -> Load -> persistent in unitofwork,从数据库重建实例。 89 /// 90 TAggregateRoot Load
(Guid id) 91 where TAggregateRoot : AggregateRoot; 92 93 ///
94 /// persistent in database -> Refresh -> persistent in unitofwork,从数据库刷新实例,场景:使用存储过程修改了一个实例,使用此方法重新刷新一下。 95 /// 96 void Refresh
(TAggregateRoot item) 97 where TAggregateRoot : AggregateRoot; 98 99 ///
100 /// 回滚所有自上次提交以后的修改。101 /// 102 void Clear();103 104 ///
105 /// 清空处于persistent in unitofwork状态的实例。106 /// 107 TRepository GetRepository
()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     ///  18     /// 基于EntityFramework的工作单元。 19     ///  20     public abstract class UnitOfWork : DbContext, IUnitOfWork 21     { 22         private readonly Dictionary
repositories = new Dictionary
(); 23 24 ///
25 /// 构造方法。 26 /// 27 protected UnitOfWork() 28 { 29 } 30 31 ///
32 /// 构造方法。 33 /// 34 protected UnitOfWork(string nameOrConnectionString) 35 : base(nameOrConnectionString) 36 { 37 } 38 39 ///
40 public bool Contains
(TAggregateRoot item) 41 where TAggregateRoot : AggregateRoot 42 { 43 item.MustNotNull("item"); 44 45 return this.Entry(item).State != EntityState.Detached; 46 } 47 48 ///
49 public void Save
(TAggregateRoot item) 50 where TAggregateRoot : AggregateRoot 51 { 52 item.MustNotNull("item"); 53 54 this.Set
().Add(item); 55 } 56 57 ///
58 public void Update
(TAggregateRoot item) 59 where TAggregateRoot : AggregateRoot 60 { 61 item.MustNotNull("item"); 62 63 this.Entry(item).State = EntityState.Modified; 64 } 65 66 ///
67 public void Persist
(TAggregateRoot item) 68 where TAggregateRoot : AggregateRoot 69 { 70 item.MustNotNull("item"); 71 72 this.Entry(item).State = EntityState.Unchanged; 73 } 74 75 ///
76 public void Delete
(TAggregateRoot item) 77 where TAggregateRoot : AggregateRoot 78 { 79 item.MustNotNull("item"); 80 81 this.Entry(item).State = EntityState.Deleted; 82 } 83 84 ///
85 public void Merge
(TAggregateRoot item) 86 where TAggregateRoot : AggregateRoot 87 { 88 item.MustNotNull("item"); 89 90 var persistItem = this.Set
().Find(item.Id); 91 92 this.Entry(persistItem).CurrentValues.SetValues(item); 93 } 94 95 ///
96 public void Evict
(TAggregateRoot item) 97 where TAggregateRoot : AggregateRoot 98 { 99 item.MustNotNull("item");100 101 this.Entry(item).State = EntityState.Detached;102 }103 104 ///
105 public void Flush()106 {107 try108 {109 base.SaveChanges();110 }111 catch (DbUpdateConcurrencyException ex)112 {113 throw new OptimisticConcurrencyException(ex.Message, ex);114 }115 }116 117 public TAggregateRoot Load
(Guid id)118 where TAggregateRoot : AggregateRoot119 {120 return this.Set
().Find(id);121 }122 123 public void Refresh
(TAggregateRoot item)124 where TAggregateRoot : AggregateRoot125 {126 item.MustNotNull("item");127 128 this.Entry(item).Reload();129 }130 131 ///
132 public void Clear()133 {134 base.ChangeTracker.Entries()135 .ToList()136 .ForEach(entry => entry.State = System.Data.EntityState.Detached);137 }138 139 ///
140 public TRepository GetRepository
()141 where TRepository : IRepository142 {143 var key = typeof(TRepository);144 145 if (!repositories.ContainsKey(key))146 {147 var repository = ServiceLocator.Current.GetInstance
();148 (repository as IEntityFrameworkRepository).Owner = this;149 repositories[key] = repository;150 }151 152 return (TRepository)repositories[key];153 }154 }155 }

备注

其实我们经常忽略一个关于接口的问题,就是异常本身也是API的一部分,虽然这部分在C#中没有办法显式的表达,等我的朋友实现完了NH版本的工作单元的开发,我们就继续对异常进行抽象。

 

转载地址:http://pwqcx.baihongyu.com/

你可能感兴趣的文章
如何进行跨网段的远程唤醒
查看>>
数据挖掘-同比与环比
查看>>
nginx+php详解
查看>>
我的友情链接
查看>>
RedHat6 管理应用服务【11】
查看>>
stm32F10x复习-1
查看>>
20135226黄坤信息安全系统设计基础期末总结
查看>>
轻松快捷创建VSFTP虚拟用户
查看>>
[转]Javascript原型继承
查看>>
[转] vue异步处理错误
查看>>
CSS 3D动画概述菜鸟级解读之一
查看>>
分布式系列文章 —— 从 ACID 到 CAP / BASE
查看>>
方法签名与方法重载
查看>>
matlab进行地图仪的绘制
查看>>
Strawberry Perl CPAN Install Module 安装 Module 方法
查看>>
kindeditor.net应用
查看>>
函数preg_replace()与str_replace()
查看>>
【Android开源框架】使用andbase开发框架实现绘制折线图
查看>>
Linux c括号作用域【原创笔记】
查看>>
用IPFS和以太坊存储数据
查看>>