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

本文共 2892 字,大约阅读时间需要 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();
    
}
}

顺利得到结果

转载于:https://www.cnblogs.com/zhangchenliang/archive/2012/12/16/2820962.html

你可能感兴趣的文章
shell编程前言(一)
查看>>
5、centos7.*配置yum的EPEL源及其它源
查看>>
JSON前后台简单操作
查看>>
shell中一些常见的文件操作符
查看>>
第一次作业
查看>>
ssh连接提示问题
查看>>
CentOS 7 装vim遇到的问题和解决方法
查看>>
JavaScript基础教程1-20160612
查看>>
使用第三方类、库需要注意的正则类RegexKitLite的使用
查看>>
iOS \U7ea2 乱码 转换
查看>>
FCN图像分割
查看>>
ios xmpp demo
查看>>
设计模式之-工厂模式、构造函数模式
查看>>
python matplotlib 中文显示参数设置
查看>>
数据库事务隔离级别
查看>>
os模块大全详情
查看>>
【ros】Create a ROS package:package dependencies报错
查看>>
从内积的观点来看线性方程组
查看>>
kali linux 更新问题
查看>>
HDU1576 A/B【扩展欧几里得算法】
查看>>