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. SpringCloud(二)之Ribbon的实现负载均衡的基本应用

    一 Ribbon简介     Ribbon是Netflix发布的负载均衡器,它是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现.通过Spring Cloud的封装 ...

  2. js内存空间及this关键词详解

    http://mp.weixin.qq.com/s/FYFepXmkzzDYNLKhpovYFA

  3. PHP(面向对象)连接数据库,实现基本的增删改查

    https://blog.csdn.net/qq_37674858/article/details/78921485 --------------------- 本文来自 周子青 的CSDN 博客 , ...

  4. [Kerberos] Kerberos教程(二)

    4 Kerberos操作 最后,在获得前面段落中描述的概念后,可以讨论Kerberos如何运作.我们将通过列出和描述在身份验证期间在客户端和KDC之间以及客户端和应用程序服务器之间的每个数据包来执行此 ...

  5. 分析Python中解析构建数据知识

    分析Python中解析构建数据知识 Python 可以通过各种库去解析我们常见的数据.其中 csv 文件以纯文本形式存储表格数据,以某字符作为分隔值,通常为逗号:xml 可拓展标记语言,很像超文本标记 ...

  6. HTML DOM firstChild lastChild nextSibling previousSibling 属性_获取属性值的undefined问题

    <html> <head> <title>HTML示例</title> <style type="text/css"> ...

  7. 在TeamCity中执行gtest单元测试

    1. 在Visual Studio 2017中新建一个gtest项目 Sample-Test1.这个项目会自动安装“Microsoft.googletest.v140.windesktop.msvcs ...

  8. svn clearup svn cleanup failed–previous operation has not finished; run cleanup if it was int错误的解决办法

    今天svn提交,出现异常:svn cleanup failed–previous operation has not finished; run cleanup if it was interrupt ...

  9. Y2K Accounting Bug POJ2586

    Description Accounting for Computer Machinists (ACM) has sufferred from the Y2K bug and lost some vi ...

  10. 【转载】android权限大全

    1.android.permission.WRITE_USER_DICTIONARY 允许应用程序向用户词典中写入新词 2.android.permission.WRITE_SYNC_SETTINGS ...