关于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 ...
随机推荐
- router路由去掉#!的踩坑记
项目中在研究去掉router#!的过程中的踩坑过程.
- Python之路Day20-Django一对一(多)以及Ajax
上节内容回顾 问题一:Django请求生命周期 -> URL对应关系(匹配) -> 视图函数 -> 返回用户字符串-> URL对应关系(匹配) -> 视图函数 -> ...
- css三级菜单效果
一个简单实用的css三级菜单效果 <!doctype html> <html> <head> <meta charset="utf-8"& ...
- linux配置ftp高级权限
建一个用于管理的ftp高级账号,ftproot,定义它的目录,也就是我们存放项目的地址,所属组www, useradd -d /home/www -g www ftproot www里存放很多项目,我 ...
- Xcode 升级后,常常遇到的遇到的警告、错误,解决方法(转)
从sdk3.2.5升级到sdk 7.1中间废弃了很多的方法,还有一些逻辑关系更加严谨了.1,警告:“xoxoxoxo” is deprecated解决办法:查看xoxoxoxo的这个方法的文档,替换 ...
- svn相关知识点
1.查找linux操作系统:uname -a 2.svn 安装:yum install -y subversion 3.svn操作命令 a.将文件checkout到本地目录: svn co svn:/ ...
- 浏览器中CSS的BUG
对于web2.0的过度,请尽量用xhtml格式写代码,而且DOCTYPE 影响 CSS 处理,作为W3C的标准,一定要加 DOCTYPE声明. 其它请参考:CSS hack 针对IE6,IE7,fir ...
- 学习设计模式第二十七 - GoF之外简单工厂模式
示例代码来自<深入浅出设计模式>和<大话设计模式> 概述 简单工厂模式又被称为静态工厂模式,属于类的创建型模式.其实质是由一个工厂类根据传入的参量,动态决定应该创建出哪一个产品 ...
- iOS开发系列--C语言之基础知识
概览 当前移动开发的趋势已经势不可挡,这个系列希望浅谈一下个人对IOS开发的一些见解,这个IOS系列计划从几个角度去说IOS开发: C语言 OC基础 IOS开发(iphone/ipad) Swift ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之三unlock方法分析
前篇博客LZ已经分析了ReentrantLock的lock()实现过程,我们了解到lock实现机制有公平锁和非公平锁,两者的主要区别在于公平锁要按照CLH队列等待获取锁,而非公平锁无视CLH队列直接获 ...