博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一个对Entity Framework数据层的封装
阅读量:7195 次
发布时间:2019-06-29

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

最近在研究DDD,同时也下载了一些基于DDD做的成熟案例用来学习,有一些吧,过于成熟,顺便就从里面取了取别的经,比如这个ByteartRetail项目,里面对数据的操作狠花了我一些时间

展开看看

其实有个问题很明显,同为基于DDD进行的项目架构设计,不同人设计的项目分层、命名和里面放的东西都不相同,看样子DDD这玩意,纯粹就是一个思维方式,所以也只能从各种实现里面找自己最能懂的来实现适合自己的架构方式了。很抱歉,因为找示例的时候找得太多,就忘了每个项目的来处了,不过大多是在StackOverflow里面别人推荐的,你们可以去找找看。

上面这个项目它实现了用A.And(B).And(C).Or(D)这种方式来动态生成lambda表达式,这个不在本篇讨论范围内,看一看它是怎么用Repository模式和Unit Of Work模式来做数据层的

因为用的EF框架,所以我们直接看EntityFrameworkRepository,对外就是用的它的方法。

这个图我简化了一些,但骨干都有了,首先,IRepository容器接口定义了基本的增删改查接口(复杂查询、分页都可以做在里面)

其次,IUnitOfWork接口按unit of work思想把数据操作和提交分离,听起来很高深,但实现上,不过是在所有的数据操作里面不去SaveChanges(),而是通过标记状态的方式改变数据(由IRepositoryContext定义),最后统一由Commit方法来提交更改。出于各司其职的需要,所以把简单的事变成了三个接口,分别处理:增删改的对外接口、增删改的标记动作、事务的提交和回滚,这三件事

于是,分别有了Repository和RepositoryContext这两个类,它们实现的哪个接口见上图

接下来,IEntityFrameworkRepositoryContext接口主要是为了针对Entity Framework做实现,所以加了一个DbContext的属性,也仅仅只是加了一个属性。这样,EntityFrameworkRepositoryContext实现IEntityFrameworkRepositoryContext的同时,继承Repository,就拥有了对DbContext对象进行标识增删改和提交、回滚的能力了。

到此,我们再把Repository类扩展一下,用EntityFrameworkRepository来继承之,从构造函数传入上面的包含了DbContext对象的EFcontext类(接口),把标识和提交的能力都带了进来,最终一个符合unit of work模式的具有操作DbContext对象的数据层就诞生了。

 

思路搞清了,我就简化了一下,如下:

这一次,我把Repository变为了最终暴露的类。但是实现的时候碰到了一个难题。示例程序中,DbContext对象居然是直接在EFRepositoryContext内部直接new出来的:

private 
readonly 
ThreadLocal<ByteartRetailDbContext> localCtx =
new 
ThreadLocal<ByteartRetailDbContext>(() =>
new 
ByteartRetailDbContext());

这样,上面的红字我标出了它把DbContext带进去的方式,是把dbcontext实例化了,然后整个对象变成构造函数传进去,我不行啊,这个DbContext很可能不止有一个啊,那么就只有把DbContext本身变成RepositoryContext的构造函数(而不是示例中的repositorycontext)了,然后Repository继承它。最终形成上图。

这种方式有一个缺点,就是最终的容器不是同其接口一一对应的,而是扩展了别的功能,结果就是在外部使用的时候必须用Repository实例,而不能用接口,以实现依赖注入(DI)的功能,管它呢,先告一段落吧

试用一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//测试服务接口
public 
interface 
Itest
{
    
string 
outstirng(
string 
msg);
}
 
//测试服务实现
public 
string 
outstirng()
{
    
var u =
new 
Repository<user>(
new 
myEntities());
//DbContext由此传入
    
user us = u.GetEntity(m => m.id == 2);
    
us.addr =
"update" 
+ DateTime.Now.ToString(
"ddfff"
);
    
u.Update(us);
    
us = u.GetEntity(m => m.id == 1);
    
u.Delete(us);
    
u.Commit();
//一次提交,不提交不生效
    
us = u.GetEntity(m => m.id == 2);
    
return 
us.addr;
}

在MVC4项目里测试,用了SimpleInjector做IOC的注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//注入
public 
static 
void 
Initialize()
{
    
var container =
new 
Container();
    
InitializeContainer(container);
    
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
    
container.RegisterMvcAttributeFilterProvider();
    
container.Verify();
    
DependencyResolver.SetResolver(
new 
SimpleInjectorDependencyResolver(container));
}
private 
static 
void 
InitializeContainer(Container container)
{
    
container.Register<Itest, impltest>();
}

Controller:

1
2
3
4
5
6
7
8
9
10
11
12
public 
class 
TestController : Controller
{
    
Itest svr;
    
public 
TestController(Itest service)
    
{
        
svr = service;
    
}
    
public 
string 
Index()
    
{
        
return 
svr.outstirng();
    
}
}

顺利得到结果

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

你可能感兴趣的文章
jquery 选择器汇总
查看>>
Nodejs 学习资料
查看>>
设计模式(三) 抽象工厂模式
查看>>
Hbase之修改表结构
查看>>
通过浏览器学习前端的小技巧
查看>>
APP开发之AngularJS学习
查看>>
Sass:RGB颜色函数-Mix()函数
查看>>
phpMyAdmin 错误 缺少 mysqli 扩展。请检查 PHP 配置
查看>>
Win7网上邻居提示未授予用户在此计算机上的请求登录类型解决办法
查看>>
golang包快速生成base64验证码
查看>>
Visual studio 下C++工程相关经验
查看>>
七、SSR(服务端渲染)
查看>>
django--app(六)
查看>>
洛谷P3379 【模板】最近公共祖先(LCA)
查看>>
获取一个表单字段中多条数据并转化为json格式
查看>>
c#中的变量,属性,字段
查看>>
JS实现延迟载入图片
查看>>
游戏开发中的人工智能
查看>>
Ubuntu 安装BCM 43142无线网卡驱动
查看>>
iOS 疑难杂症 — — UIButton 点击卡顿/延迟
查看>>