WedeNet2018.Infrastructure-基础设施层:
结构如下:

Tools结构如下:

考虑到系统可能会有多个数据上下文(暂时以两个为例),所以根据需要定义两个T4模板用来生成对应的entities和dbcontext类,每个T4模板对应一个数据库连接,这些数据库连接配置在应用层的配置文件中(如UI层web.config或者WCF寄宿层的app.config)。

生成的结果如下:

在此,我把UnitOfWork和Repository都看做为组件,和它们所依赖的dbcontext都统一放在了Components目录下。
仓储需要包装不同的EF entitiy,自然需要定义为泛型接口,如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks; namespace WedeNet2018.Infrastructure.Components
{
public interface IRepository<T>
where T : class
{
IQueryable<T> All();
IQueryable<T> Filter(Expression<Func<T, bool>> predicate);
T Find(params object[] keys);
T Find(Expression<Func<T, bool>> predicate);
void Insert(T t);
void Insert(IEnumerable<T> entities);
void Delete(T t);
void Delete(IEnumerable<T> entities);
void Update(T t);
void Update(IEnumerable<T> entities);
void Clear();
}
}

接口的实现如下:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks; namespace WedeNet2018.Infrastructure.Components
{
public class EntityRepository<TContext,TEntity> : IRepository<TEntity>
where TContext : DbContext
where TEntity : class
{
protected TContext context;
protected DbSet<TEntity> dbSet; public EntityRepository(TContext dbContext)
{
context = dbContext;
dbSet = context.Set<TEntity>();
} protected virtual TContext Context { get { return context; } }
protected virtual DbSet<TEntity> DbSet { get { return dbSet; } }
/// <summary>
/// 查询全部当前实体数据集
/// </summary>
/// <returns>IQueryable集合</returns>
public virtual IQueryable<TEntity> All()
{
return DbSet.AsQueryable();
}
/// <summary>
/// 条件查询当前实体数据集
/// </summary>
/// <param name="predicate">查询条件</param>
/// <returns>IQueryable集合</returns>
public virtual IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate).AsQueryable<TEntity>();
} /// <summary>
/// 查找指定主键的数据
/// </summary>
/// <param name="keys">指定主键</param>
/// <returns>符合编号的记录,不存在返回null </returns>
public virtual TEntity Find(params object[] keys)
{
return DbSet.Find(keys); } /// <summary>
/// 查找指定条件的单条数据
/// </summary>
/// <param name="predicate">查询条件</param>
/// <returns>返回符合条件的数据,或者null</returns>
public virtual TEntity Find(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.FirstOrDefault(predicate);
}
/// <summary>
/// 上下文中插入单个实体
/// </summary>
/// <param name="entity"></param>
public virtual void Insert(TEntity entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
{
Context.Entry(entity).State = EntityState.Added;
//DbSet.Add(entity);
}
}
/// <summary>
/// 上下文中批量插入实体
/// </summary>
/// <param name="entities"></param>
public virtual void Insert(IEnumerable<TEntity> entities)
{
try
{
Context.Configuration.AutoDetectChangesEnabled = false;
foreach (TEntity entity in entities)
{
Insert(entity);
}
}
finally
{
Context.Configuration.AutoDetectChangesEnabled = true;
}
} /// <summary>
/// 上下文中删除单个实体
/// </summary>
/// <param name="entity"></param>
public virtual void Delete(TEntity entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
{
DbSet.Attach(entity);
}
DbSet.Remove(entity);
}
/// <summary>
/// 上下文中批量删除实体
/// </summary>
/// <param name="entities"></param>
public virtual void Delete(IEnumerable<TEntity> entities)
{
try
{
Context.Configuration.AutoDetectChangesEnabled = false;
foreach (TEntity entity in entities)
{
Delete(entity);
}
}
finally
{
Context.Configuration.AutoDetectChangesEnabled = true;
}
}
/// <summary>
/// 上下文中更新单个实体
/// </summary>
/// <param name="entity"></param>
public virtual void Update(TEntity entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
{
DbSet.Attach(entity);
}
Context.Entry(entity).State = EntityState.Modified;
}
/// <summary>
/// 上下文中批量更新实体
/// </summary>
/// <param name="entities"></param>
public virtual void Update(IEnumerable<TEntity> entities)
{
try
{
Context.Configuration.AutoDetectChangesEnabled = false;
foreach (TEntity entity in entities)
{
Update(entity);
}
}
finally
{
Context.Configuration.AutoDetectChangesEnabled = true;
}
} public virtual void Clear()
{ }
}
}

在这个仓储基类里,引入了该仓储依赖的dbcontext,这个dbcontext会在系统初始化该仓储的时候传入,并且是单例的。这样才能保证UnitOfWork操作的一致性。
另外,针对不同的dbcontext,我也定义了对应的抽象类,如:

目的是在做IOC的时候一个具体类型必须对应一个基类,而在这两个抽象类内部都继承了DbContext,如:

// <auto-generated>
// 此代码由工具生成。
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// 如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类进行实现。
// </auto-generated>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations; namespace WedeNet2018.Infrastructure
{
public abstract class AbsWedeDBContex:DbContext
{
//连接字符串名称:基于Config文件中连接字符串的配置
const string connectionStringName = "constring"; public AbsWedeDBContex()
: base(connectionStringName)
{ }
}
}

接下来就是UnitOfWork,接口定义如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks; namespace WedeNet2018.Infrastructure.Components
{
/// <summary>
/// 定义工作单元统一接口
/// </summary>
public interface IUnitOfWorks
{
IQueryable<T> Where<T>(Expression<Func<T, bool>> predicate) where T : class;
IQueryable<T> All<T>() where T : class; T Find<T>(object id) where T : class;
T Find<T>(Expression<Func<T, bool>> predicate) where T : class; void Add<T>(T t) where T : class;
void Add<T>(IEnumerable<T> items) where T : class; void Update<T>(T t) where T : class;
void Update<T>(IEnumerable<T> items) where T : class; void Delete<T>(T t) where T : class;
void Delete<T>(IEnumerable<T> items) where T : class; void Clear<T>() where T : class;
bool IsCommitted { get; } int Commit();
}
}

和上面定义了两个dbcontext抽象基类一样,出于IOC考虑,这里也定义了两个实现了IUnitOfWorks接口的接口,如:

下面是对应的实现类,如:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WedeNet2018.Common; namespace WedeNet2018.Infrastructure.Components
{
/// <summary>
/// 实现一个工作单元,将使用NInject注册为单例
/// </summary>
/// <typeparam name="TDBContext">该工作单元使用的数据上下文类型</typeparam>
public class XF0816UnitOfWorks<TDBContext> : IXF0816UnitOfWorks, IDisposable
where TDBContext : DbContext
{
protected TDBContext dbContext; public XF0816UnitOfWorks(TDBContext context)
{
dbContext = context;
} //构造通用的Repository
private IDictionary<Type, object> repositoryTable = new Dictionary<Type, object>(); //注册其它的Repository
public void Register<T>(IRepository<T> repository) where T : class
{
var key = typeof(T);
if (!repositoryTable.ContainsKey(key))
repositoryTable.Add(key, repository);
} private IRepository<T> GetRepository<T>()
where T : class
{
IRepository<T> repository = null;
var key = typeof(T); if (repositoryTable.ContainsKey(key))
repository = (IRepository<T>)repositoryTable[key];
else
{
repository = GenericRepository<T>();
repositoryTable.Add(key, repository);
} return repository;
} protected virtual IRepository<T> GenericRepository<T>() where T : class
{
return new EntityRepository<TDBContext, T>(dbContext);
}
/// <summary>
/// 条件查询当前实体数据集
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="predicate">查询条件</param>
/// <returns>IQueryable集合</returns>
public System.Linq.IQueryable<T> Where<T>(Expression<Func<T, bool>> predicate)
where T : class
{
return GetRepository<T>().Filter(predicate);
}
/// <summary>
/// 查询全部当前实体数据集
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <returns>IQueryable集合</returns>
public System.Linq.IQueryable<T> All<T>() where T : class
{
return GetRepository<T>().All();
} /// <summary>
/// 查找指定主键的数据
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="id">实体主键</param>
/// <returns>符合编号的记录,不存在返回null</returns>
public T Find<T>(object id) where T : class
{
return GetRepository<T>().Find(id);
}
/// <summary>
/// 查找指定条件的单条数据
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="predicate">查询条件</param>
/// <returns>返回符合条件的数据,或者null</returns>
public T Find<T>(Expression<Func<T, bool>> predicate) where T : class
{
return GetRepository<T>().Find(predicate);
}
/// <summary>
/// 上下文中插入单个实体
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="t">实体</param>
public void Add<T>(T t) where T : class
{
GetRepository<T>().Insert(t);
}
/// <summary>
/// 上下文中批量插入实体
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="items">实体集合</param>
public void Add<T>(IEnumerable<T> items) where T : class
{
GetRepository<T>().Insert(items);
}
/// <summary>
/// 上下文中更新单个实体
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="t">实体</param>
public void Update<T>(T t) where T : class
{
GetRepository<T>().Update(t);
}
/// <summary>
/// 上下文中批量更新实体
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="items">实体集合</param>
public void Update<T>(IEnumerable<T> items) where T : class
{
GetRepository<T>().Update(items);
}
/// <summary>
/// 上下文中删除单个实体
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="t">实体</param>
public void Delete<T>(T t) where T : class
{
GetRepository<T>().Delete(t);
}
/// <summary>
/// 上下文中批量删除实体
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="items">实体集合</param>
public void Delete<T>(IEnumerable<T> items) where T : class
{
GetRepository<T>().Delete(items);
} public void Clear<T>() where T : class
{
GetRepository<T>().Clear();
} /// <summary>
/// 当前单元操作是否已被提交
/// </summary>
public bool IsCommitted { get; private set; } /// <summary>
/// 提交当前工作单元
/// </summary>
/// <returns></returns>
public int Commit()
{
try
{
int result = dbContext.SaveChanges();
return result;
}
catch (DbUpdateException e)
{
if (e.InnerException != null && e.InnerException.InnerException is SqlException)
{
SqlException sqlEx = e.InnerException.InnerException as SqlException;
string msg = SqlDataHelper.GetSqlExceptionMessage(sqlEx.Number);
throw PublicHelper.ThrowDataAccessException("提交数据更新时发生异常:" + msg, sqlEx);
}
throw;
}
} public void Dispose()
{
if (dbContext != null)
{
dbContext.Dispose();
}
GC.SuppressFinalize(this);
} }
}

到此为止,Infrastructure-基础设施层已经构建好了。

搭建自己的框架WedeNet(二)的更多相关文章

  1. 架构实战项目心得(七):使用SpringBoot+Dubbo+Mybatisplus+Oracle搭建后台项目框架(二)

    接下来我们将整合mybatisplus+Oracle,实现一个简单的查询.(期间踩了很多坑,遇到一些问题,还好慢慢解决了.现在是通过配置文件的方式来进行dubbo服务的注册和发布,希望以后能在学习和实 ...

  2. 搭建自己的框架WedeNet(五)

    WedeNet2018.WedeWcfServices-WCF服务层:结构如下: 就是定义了服务契约接口和服务类,以OrderServices为例,如下: using System; using Sy ...

  3. 搭建自己的框架WedeNet(一)

    框架用到的技术: EF.UnitOfWork+Repository.Ninject.log4net.WCF.MVC.T4.windows服务.AOP前端技术:Bootstrap.layer.jQuer ...

  4. 搭建自己的框架WedeNet(四)

    WedeNet2018.Web-UI层:结构如下: 首先,在Controller中定义BaseController,以便加入统一处理逻辑,如下: using log4net; using System ...

  5. 搭建自己的框架WedeNet(三)

    WedeNet2018.BussinessLogic-业务逻辑层:结构如下: 基类: using System; using System.Collections.Generic; using Sys ...

  6. 使用SSM框架 搭建属于自己的APP二维码合成、解析、下载

    最近公司的app上线了,在推广APP的时候出现了一个问题,因为Android和IOS的下载地址不一样,那么在推广的时候就要推广两个二维码,这样比较麻烦,如何简化我们的推广,让IOS用户扫描二维码的时候 ...

  7. MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)

    前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...

  8. Windows环境搭建Web自动化测试框架Watir

    Windows环境搭建Web自动化测试框架Watir 一.前言     Web自动化测试一直是一个比较迫切的问题,对于现在web开发的敏捷开发,却没有相对应的敏捷测试,故开此主题,一边研究,一边将We ...

  9. python webdriver 从无到有搭建数据驱动自动化测试框架的步骤和总结

    一步一步搭建数据驱动测试框架的过程和总结 跟吴老学了搭建自动化数据驱动的框架后,我在自己练习的时候,尝试从简单的程序进行一点一点的扩展和优化,到实现这个数据驱动的框架. 先说一下搭建自动化测试框架的目 ...

随机推荐

  1. ycache中redis主备功能设计及使用说明

    方案概述: 对于ycache-client,如下图,在一致性hash环上的每个节点都有一个备用的节点.正常情况下slave节点不参与key的分配(冷备).只有当master挂了,ycache clie ...

  2. [面试] Java高级软件工程师面试考纲(转)

    如果要应聘高级开发工程师职务,仅仅懂得Java的基础知识是远远不够的,还必须懂得常用数据结构.算法.网络.操作系统等知识.因此本文不会讲解具体的技术,笔者综合自己应聘各大公司的经历,整理了一份大公司对 ...

  3. Android之MVVM开发模式

    MVVM 模式简介 MVVM模式是指Model-View-ViewModel.相信看过笔者关于MVP的文章的读者也会发现,无论如何抽象化,在我们的View层中是无法避免的要处理一部分逻辑的.而MVVM ...

  4. js对象和jQuery对象的区别

    (1)js对象的三种基本定位方式 (A)通过ID属性:document.getElementById() (B)通过NAME属性:document.getElementsByName() (C)通过标 ...

  5. html里 调整字间距

    使用字与字的间距可设置letter-spacing属性实现,例如:1.p{letter-spacing:15px;}即表示<p>这是一段文字</p>标签里的文字间距为15px. ...

  6. Java注解(Annotation)详解

    转: Java注解(Annotation)详解 幻海流心 2018.05.23 15:20 字数 1775 阅读 380评论 0喜欢 1 Java注解(Annotation)详解 1.Annotati ...

  7. Requests API

    Requests API http://docs.python-requests.org/en/latest/ requests的具体安装过程请看: http://docs.python-reques ...

  8. Windows切换窗口

    方法1  Alt+Tab 切换到自己需要的窗口即可!!!! 方法2 Windows+Tab键

  9. Linux系统管理_主题01 :初识Linux_1.5 与Linux进行交互_echo_nano_Tab_whoami

    [root@izkfv3zmvcl0omz ~]# 其中,'root'为登录用户名,'izkfv3zmvcl0omz'为登录主机名,’~’ 表示当前用户正处在 root 用户的 家目录中,’#’则表示 ...

  10. const成员变量

    #include <iostream> using namespace std; class A { public: A(int size) : SIZE(size) {}; privat ...