关于MVC EF架构及Repository模式的一点心得
一直都想写博客,可惜真的太懒了或者对自己的描述水平不太自信,所以。。。一直都是不想写的状态,关于领域驱动的东西看了不少,但是由于自己水平太差加上工作中实在用不到,所以一直处于搁置状态,最近心血来潮突然想重新写一个自己的项目架构,于是开始了新一论的学习历程。
在设计之前我理了一下自己的大致需求也参考了不同人的项目架构,在此特别感谢郭明峰的OSharp给我的启示,每个人对架构的需求和使用习惯都是不一至的,在不同大小的项目上使用的架构也不尽相同,如何取舍性能、开发速度及维护性的问题上每开发者都在自己心中有一杆秤,下面谈谈我理想中的架构,它应该提供一些常用的操作封装及各种工具方便实现多个功能,他应该包括数据操作的方便处理,他应该提供日志及缓存的处理功能,它的每种实现是自己换的但又得具有默认值让我在做私单的时候更快捷方便,基于以上特点于是总结了如下模块:
1,工具库:提供了各种常用操作,如字符串截取,各种验证之类的helper类
2,核心库:提供缓存日志数据的接口及缓存日志的基础实现
3,WEB库:针对网站相关的扩展及操作封装
4,MVC库:针对MVC网站的相关扩展及操作封装
5,基础数据库模块实现库(如:EF)
回到每个架构的重点:数据访问模块上来,现在比较流行使用EF+ IUnitOfWork+Repository来实现数据的处理,诚然这种方式让每一个模块相互的依赖变得更小,更方便测试,更XXX,但是在我的实践中,还是发现他真的麻烦,在我做一个中小项目的时候,添加一个普通的表不得不去添加实体,实体配置,仓储接口,仓储实现,服务接口,服务实现,controller viewmodel,view一系列下来即便是拷贝也是非常慢,即使我们可以用代码生成器,我还是觉得太麻烦了。当然Repository模式的反对者也不少,作为一种数据操作的隔离手段,我个人觉得Repository还是很有必要存在的,经过各种取舍,最后自己使用了一种折中的方式来使用Repository,我的方式是使用IStore来代替IUnitOfWork,本质是一样的,只是IStore实现的功能要多一些,同时使用了IStore使得我们可以很容易的替换我们的数据库功能实现,如下图:

由于一般的项目不需要一人写定义一人写实现,所以直接省去了IUserRepository及IUserService这种并不会修改实现的接口,当然如果有团队共同开发的时候使用也是完全没有问题的,有了以上的图就开以开始实现代码了:
IDataStore:
/// <summary>
/// 数据存储器接口
/// </summary>
public interface IStore : IDisposable
{
#region UnitOfWork
/// <summary>
/// 获取或设置 是否开启事务提交
/// </summary>
bool TransactionEnabled { get; set; }
/// <summary>
/// 提交操作
/// </summary>
bool Commit();
/// <summary>
/// 异步提交
/// </summary>
Task<bool> CommitAsync();
#endregion #region 基础操作
/// <summary>
/// 添加对像
/// </summary>
void Add<TEntity>(TEntity entity) where TEntity : class;
/// <summary>
/// 更新对像
/// </summary>
void Update<TEntity>(TEntity entity) where TEntity : class;
/// <summary>
/// 删除对像
/// </summary>
void Remove<TEntity>(TEntity entity) where TEntity : class;
#endregion #region 查询操作
/// <summary>
/// 获取数据集查询对像
/// </summary>
IQueryable<TEntity> GetQueryEntities<TEntity, TKey>() where TEntity : class;
#endregion
}
IRepository:
/// <summary>
/// 仓储接口
/// </summary>
/// <typeparam name="TEntity">实体类型</typeparam>
/// <typeparam name="TKey">实体主键类型</typeparam>
public interface IRepository<TEntity, TKey>
{
#region 属性
/// <summary>
/// 获取当前数据存储器
/// </summary>
IStore DataStore { get; }
/// <summary>
/// 获取当前实体的查询数据集
/// </summary>
IQueryable<TEntity> Entities { get; }
#endregion #region 基础操作
/// <summary>
/// 添加实体到仓库
/// </summary>
void Add(TEntity entity);
/// <summary>
/// 更新仓库中的实体
/// </summary>
void Update(TEntity entity);
/// <summary>
/// 从仓库删除指定key的实体
/// </summary>
void Remove(TEntity entity);
#endregion #region 查询
/// <summary>
/// 获取指定key的实体
/// </summary>
TEntity FindByKey(TKey key);
#endregion
}
RepositroyBase:
/// <summary>
/// 仓储基类
/// </summary>
public abstract class RepositoryBase<TEntity, TKey> : IRepository<TEntity, TKey>
where TEntity : EntityBase<TKey>, new()
{ public IStore DataStore { get; set; } public IQueryable<TEntity> Entities
{
get { return this.DataStore.GetQueryEntities<TEntity, TKey>(); }
} public void Add(TEntity entity)
{
this.DataStore.Add<TEntity>(entity);
} public void Update(TEntity entity)
{
this.DataStore.Update<TEntity>(entity);
} public void Remove(TEntity entity)
{
this.DataStore.Remove<TEntity>(entity);
} public TEntity FindByKey(TKey key)
{
return this.Entities.Where(t => t.Id.Equals(key)).SingleOrDefault();
}
}
当然BaseEntity这种东西就看自己爱好添加了,按key删除,按条件更新的方法这里就不写了
,另外关于返回Repository返回IEnumerable还是IQueryable这个问题我个人认为如果不按照DDD的的标准来看,一个仓库每次拿你想要的东西还是给你一个通道你想拿多少就拿多少本质上都是可以的,不过对于隔离开发人员直接操作数据确实存在隐患,不过谁叫他简单呢?看完定义,然后如果要使用EF做为ORM来操作数据库或者任意继承至IDataStore的库来完成数据操作,不过这里要自己写的话,解析表达式还是有点困难的。。贴下简单EF基类的简单实现:
/// <summary>
/// EF数据存储器(抽象类)
/// </summary>
public abstract class EFDataStore : DbContext, IStore
{
#region DbContext
protected EFDataStore() { }
protected EFDataStore(DbCompiledModel model) : base(model) { }
public EFDataStore(string nameOrConnectionString) : base(nameOrConnectionString) { }
public EFDataStore(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection) { }
public EFDataStore(ObjectContext objectContext, bool dbContextOwnsObjectContext) : base(objectContext, dbContextOwnsObjectContext) { }
public EFDataStore(string nameOrConnectionString, DbCompiledModel model) : base(nameOrConnectionString, model) { }
public EFDataStore(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection) : base(existingConnection, model, contextOwnsConnection) { }
/// <summary>
/// 实体映射集合
/// </summary>
public IEnumerable<IEntityMapper> EntityConfigurations { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//foreach (var mapper in EntityConfigurations)
//{
// mapper.RegistTo(modelBuilder.Configurations);
//}
}
#endregion public bool TransactionEnabled { get; set; } public IQueryable<TEntity> GetQueryEntities<TEntity, TKey>() where TEntity : class
{
return this.Set<TEntity>();
} public bool Commit()
{
var r = this.SaveChanges();
//this.Dispose();
return r > ;
} public async Task<bool> CommitAsync()
{
return (await this.SaveChangesAsync()) > ;
} public void Add<TEntity>(TEntity entity) where TEntity : class
{
this.Set<TEntity>().Add(entity);
} public void Update<TEntity>(TEntity entity) where TEntity : class
{
this.Entry(entity).State = EntityState.Modified;
} public void Remove<TEntity>(TEntity entity) where TEntity : class
{
this.Entry(entity).State = EntityState.Deleted;
}
}
这。写着写着自己都有点不知所云了,希望对正在学习阶段的朋友有一点点帮助!
关于MVC EF架构及Repository模式的一点心得的更多相关文章
- ASP.Net MVC+EF架构
ASP.Net MVC是UI层的框架,EF是数据访问的逻辑. 如果在Controller中using DbContext,把查询的结果的对象放到cshtml中显示,那么一旦在cshtml中访问关联属性 ...
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
项目开发中的一些注意事项以及技巧总结 1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...
- MVC架构中的Repository模式 个人理解
关于MVC架构中的Repository模式 个人理解:Repository是一个独立的层,介于领域层与数据映射层(数据访问层)之间.它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接 ...
- MVC实用架构设计(三)——EF-Code First(1):Repository,UnitOfWork,DbContext
前言 终于到EF了,实在不好意思,最近有点忙,本篇离上一篇发布已经一个多星期了,工作中的小迭代告一段落,终于有点时间来继续我们的架构设计了,在这里先对大家表示歉意. 其实这段时间我并不是把这个系列给忘 ...
- 基于Repository模式设计项目架构—你可以参考的项目架构设计
关于Repository模式,直接百度查就可以了,其来源是<企业应用架构模式>.我们新建一个Infrastructure文件夹,这里就是基础设施部分,EF Core的上下文类以及Repos ...
- MVC+EF 理解和实现仓储模式和工作单元模式
MVC+EF 理解和实现仓储模式和工作单元模式 原文:Understanding Repository and Unit of Work Pattern and Implementing Generi ...
- MVC Repository模式
近来发现很多ASP.NET MVC的例子中都使用了Repository模式,比如Oxite,ScottGu最近发布的免费的ASP.NET MVC教程都使用了该模式.就简单看了下. 在<企业架构模 ...
- (转)MVC中的Repository模式
1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository. 2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名 ...
- C# 框架是什么?MVC是什么 ?工厂模式是什么?设计模式是什么?三层架构是什
C# 框架是什么?MVC是什么 ?工厂模式是什么?设计模式是什么?三层架构是什么?如果要学我该从何学起??? C# 框架看这里http://download.csdn.net/source/25784 ...
随机推荐
- 【Telerik】查询控件<telerik:RadMaskedTextBox>的使用
在SilverLight项目中,实现模糊查询,并将值绑定到列表中,使用了Telerik中的<telerik:RadMaskedTextBox>控件. 要先添加命名空间的引用: xmlns: ...
- Python 爬虫1——爬虫简述
Python除了可以用来开发Python Web之后,其实还可以用来编写一些爬虫小工具,可能还有人不知道什么是爬虫的. 一.爬虫的定义: 爬虫——网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区 ...
- css解决display:inline-block;产生的缝隙(间隙)
今天在做H5的水平滑动卡片时用到了display:inline-block;却发现处在同一水平线上的元素之间居然产生了缝隙,这很显然不是我想要的效果,所以我就换成了左浮动,这样缝隙的问题是解决了,但是 ...
- Spark 应用程序调优
对于很多刚接触Spark的人来说,可能主要关心数据处理的逻辑,而对于如何高效运行Spark应用程序了解较少.由于Spark是一种分布式内存计算框架,其性能往往受限于CPU.内存.网络等多方面的因素,对 ...
- win7 x64 vs2010 directShow开发环境配置
近来工作需要,要用dirrectShow写一个视频播放的demo验证自己的想法.开发环境配置了好久都没有成功,最后终于弄完,现在记录下来,以后有同学遇到同样问题,可以以此法解决. windows SD ...
- 比achartengine更加强大的Android图表控件。
比achartengine更加强大的图表控件MPAndroidChart. 详细使用及demo:http://www.see-source.com/androidwidget/detail.html? ...
- 微信支付:JSAPI支付一直提示URL未注册
今天意外碰上了这个问题,想想微信的坑真多…… 解决办法: 首先要看微信公众号里的 支付授权目录 是否已正确填写,还要验证 url大小写 必须相同 其次查看一下自己请求的地址是否与上面填写的是否一样!u ...
- 如何让Maple中的数学引擎进入你的桌面应用程序和网站
MapleNET数学服务套件将Maple 2015强大的数学引擎引入您的应用程序和网站.使用MapleNET,您可以添加数学计算和可视化功能到网页和桌面程序中,通过互联网/局域网分享“活”的Maple ...
- xcodebuild编译ipa
#!/bin/sh # autoBuild.sh # CTest # # Created by Ethan on 14-11-3. # Copyright (c) 2014年 Ethan. All r ...
- Hadoop学习笔记—7.计数器与自定义计数器
一.Hadoop中的计数器 计数器:计数器是用来记录job的执行进度和状态的.它的作用可以理解为日志.我们通常可以在程序的某个位置插入计数器,用来记录数据或者进度的变化情况,它比日志更便利进行分析. ...