* 在使用Entity
Framework这种ORM框架得时候,一般结合Repository仓储形式来处理业务逻辑;虽然这种模式带来很多好处,但是也会引发一些争议,在此抛开不谈,小弟结合项目经验来实现一下,欢迎大佬拍砖;
* 后续会带来Dapper
基于Repository实现,代码一些实现会兼容Dapper,所以做了一些比较丑陋得写法;但是我得想法是通过一些Ioc可以在Entity
Framework和Dapper两者之间进行切换;
* 您可以通过Nuget:Install-Package MasterChief.DotNet.Core.EF 安装使用;
* 您可以通过Github:MasterChief <https://github.com/YanZhiwei/MasterChief>
查看具体源码以及单元测试
* 欢迎Star,欢迎Issues;
插播一条求职

* 小弟拥有多年C#开发经验,从事过路灯,消防平台物联网平台开发,坐标上海;
* 如果贵司在招聘,烦请大佬考虑下,联系邮箱:MeetYan@outlook.com
标准仓储
/// <summary> /// 标准仓储接口 /// </summary> public interface IRepository { #region
Methods /// <summary> /// 删除记录 /// </summary> /// <returns>操作是否成功</returns> ///
<param name="entity">需要操作的实体类.</param> bool Delete<T>(T entity) where T :
ModelBase; /// <summary> /// 条件判断是否存在 /// </summary> ///
<returns>是否存在</returns> /// <param name="predicate">判断条件委托</param> bool
Exist<T>(Expression<Func<T, bool>> predicate = null) where T : ModelBase; ///
<summary> /// 根据id获取记录 /// </summary> /// <returns>记录</returns> /// <param
name="id">id.</param> T GetByKeyId<T>(object id) where T : ModelBase; ///
<summary> /// 条件获取记录集合 /// </summary> /// <returns>集合</returns> /// <param
name="predicate">筛选条件.</param> List<T> GetList<T>(Expression<Func<T, bool>>
predicate = null) where T : ModelBase; /// <summary> /// 条件获取记录第一条或者默认 ///
</summary> /// <returns>记录</returns> /// <param name="predicate">筛选条件.</param>
T GetFirstOrDefault<T>(Expression<Func<T, bool>> predicate = null) where T :
ModelBase; /// <summary> /// 创建一条记录 /// </summary> ///
<returns>操作是否成功.</returns> /// <param name="entity">实体类记录.</param> bool
Create<T>(T entity) where T : ModelBase; /// <summary> /// 条件查询 /// </summary>
/// <returns>IQueryable</returns> /// <param name="predicate">筛选条件.</param>
IQueryable<T> Query<T>(Expression<Func<T, bool>> predicate = null) where T :
ModelBase; /// <summary> /// 根据记录 /// </summary> /// <returns>操作是否成功.</returns>
/// <param name="entity">实体类记录.</param> bool Update<T>(T entity) where T :
ModelBase; #endregion Methods }
数据访问上下文接口
public interface IDbContext : IDisposable, IRepository, IUnitOfWork { ///
<summary> /// 执行Sql 脚本查询 /// </summary> /// <param name="sql">Sql语句</param> ///
<param name="parameters">参数</param> /// <returns>集合</returns> IEnumerable<T>
SqlQuery<T>(string sql, IDbDataParameter[] parameters); }
数据访问上下文工厂
public interface IDatabaseContextFactory { /// <summary> /// Create this
instance. /// </summary> /// <returns>The create.</returns> IDbContext
Create(); }
基于EF的DbContext
public abstract class EfDbContextBase : DbContext, IDbContext { #region
Constructors /// <summary> /// 构造函数 /// </summary> /// <param
name="dbConnection">dbConnection</param> protected EfDbContextBase(DbConnection
dbConnection) : base(dbConnection, true) { Configuration.LazyLoadingEnabled =
false; //将不会查询到从表的数据,只会执行一次查询,可以使用 Inculde 进行手动加载;
Configuration.ProxyCreationEnabled = false;
Configuration.AutoDetectChangesEnabled = false; } #endregion Constructors
#region Fields /// <summary> /// 获取 是否开启事务提交 /// </summary> public virtual bool
TransactionEnabled => Database.CurrentTransaction != null; #endregion Fields
#region Methods /// <summary> /// 显式开启数据上下文事务 /// </summary> /// <param
name="isolationLevel">指定连接的事务锁定行为</param> public void
BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified) {
if (!TransactionEnabled) Database.BeginTransaction(isolationLevel); } ///
<summary> /// 提交当前上下文的事务更改 /// </summary> /// <exception
cref="DataAccessException">提交数据更新时发生异常:" + msg</exception> public void Commit()
{ if (TransactionEnabled) try { Database.CurrentTransaction.Commit(); } catch
(DbUpdateException ex) { if (ex.InnerException?.InnerException is SqlException
sqlEx) { var msg = DataBaseHelper.GetSqlExceptionMessage(sqlEx.Number); throw
new DataAccessException("提交数据更新时发生异常:" + msg, sqlEx); } throw; } } ///
<summary> /// 创建记录 /// </summary> /// <returns>操作是否成功</returns> /// <param
name="entity">需要操作的实体类.</param> public bool Create<T>(T entity) where T :
ModelBase { ValidateOperator.Begin().NotNull(entity, "需要创建数据记录"); bool result;
try { Entry(entity).State = EntityState.Added; result = SaveChanges() > 0; }
catch (DbEntityValidationException dbEx) { throw new
Exception(dbEx.GetFullErrorText(), dbEx); } return result; } /// <summary> ///
创建记录集合 /// </summary> /// <returns>操作是否成功.</returns> /// <param
name="entities">实体类集合.</param> public bool Create<T>(IEnumerable<T> entities)
where T : ModelBase { ValidateOperator.Begin().NotNull(entities, "需要创建数据集合");
bool result; try { foreach (var entity in entities) Entry(entity).State =
EntityState.Added; result = SaveChanges() > 0; } catch
(DbEntityValidationException dbEx) { throw new
Exception(dbEx.GetFullErrorText(), dbEx); } return result; } /// <summary> ///
删除记录 /// </summary> /// <returns>操作是否成功</returns> /// <param
name="entity">需要操作的实体类.</param> public bool Delete<T>(T entity) where T :
ModelBase { ValidateOperator.Begin().NotNull(entity, "需要删除的数据记录"); bool result;
try { Entry(entity).State = EntityState.Deleted; result = SaveChanges() > 0; }
catch (DbEntityValidationException dbEx) { throw new
Exception(dbEx.GetFullErrorText(), dbEx); } return result; } /// <summary> ///
条件判断是否存在 /// </summary> /// <returns>是否存在</returns> /// <param
name="predicate">判断条件委托</param> public bool Exist<T>(Expression<Func<T, bool>>
predicate = null) where T : ModelBase { return predicate == null ?
Set<T>().Any() : Set<T>().Any(predicate); } /// <summary> /// 根据id获取记录 ///
</summary> /// <returns>记录</returns> /// <param name="id">id.</param> public T
GetByKeyId<T>(object id) where T : ModelBase {
ValidateOperator.Begin().NotNull(id, "Id"); return Set<T>().Find(id); } ///
<summary> /// 条件获取记录集合 /// </summary> /// <returns>集合</returns> /// <param
name="predicate">筛选条件.</param> public List<T> GetList<T>(Expression<Func<T,
bool>> predicate = null) where T : ModelBase { IQueryable<T> query = Set<T>();
if (predicate != null) query = query.Where(predicate); return query.ToList(); }
/// <summary> /// 条件获取记录第一条或者默认 /// </summary> /// <returns>记录</returns> ///
<param name="predicate">筛选条件.</param> public T
GetFirstOrDefault<T>(Expression<Func<T, bool>> predicate = null) where T :
ModelBase { IQueryable<T> query = Set<T>(); if (predicate != null) return
query.FirstOrDefault(predicate); return query.FirstOrDefault(); } /// <summary>
/// 条件查询 /// </summary> /// <returns>IQueryable</returns> /// <param
name="predicate">筛选条件.</param> public IQueryable<T> Query<T>(Expression<Func<T,
bool>> predicate = null) where T : ModelBase { IQueryable<T> query = Set<T>();
if (predicate != null) query = query.Where(predicate); return query; } ///
<summary> /// 显式回滚事务,仅在显式开启事务后有用 /// </summary> public void Rollback() { if
(TransactionEnabled) Database.CurrentTransaction.Rollback(); } /// <summary>
/// 执行Sql 脚本查询 /// </summary> /// <param name="sql">Sql语句</param> /// <param
name="parameters">参数</param> /// <returns>集合</returns> public IEnumerable<T>
SqlQuery<T>(string sql, IDbDataParameter[] parameters) {
ValidateOperator.Begin() .NotNullOrEmpty(sql, "Sql语句"); // ReSharper disable
once CoVariantArrayConversion return Database.SqlQuery<T>(sql, parameters); }
/// <summary> /// 根据记录 /// </summary> /// <returns>操作是否成功.</returns> /// <param
name="entity">实体类记录.</param> public bool Update<T>(T entity) where T :
ModelBase { ValidateOperator.Begin().NotNull(entity, "需要更新的数据记录"); bool result;
try { var set = Set<T>(); set.Attach(entity); Entry(entity).State =
EntityState.Modified; result = SaveChanges() > 0; } catch
(DbEntityValidationException dbEx) { throw new
Exception(dbEx.GetFullErrorText(), dbEx); } return result; } #endregion Methods
}
单元测试
[TestClass()] public class SampleServiceTests { private IKernel _kernel;
private ISampleService _sampleService; private readonly Guid _testId =
"2F6D3C43-C2C7-4398-AD2B-ED5E82D79999".ToGuidOrDefault(Guid.Empty); private
const string TestName = "EFSample"; [TestInitialize] public void SetUp() {
_kernel = new StandardKernel(new ServiceModule()); Assert.IsNotNull(_kernel);
_sampleService = _kernel.Get<ISampleService>(); //if (!_sampleService.Exist(ent
=> ent.ID == _testID)) //{ // _sampleService.Create(new EFSample() { UserName =
_testName, ID = _testID }); //} } /// <summary> /// 创建测试 /// </summary>
[TestMethod()] public void CreateTest() { bool actual =
_sampleService.Create(new EfSample() { UserName = "ef" +
DateTime.Now.ToString("MMddHHmmss") }); Assert.IsTrue(actual); actual =
_sampleService.Create(new EfSample() { UserName = "ef" +
DateTime.Now.ToString("MMddHHmmss") }); Assert.IsTrue(actual); actual =
_sampleService.Create(new EfSample() { UserName = "ef" +
DateTime.Now.ToString("MMddHHmmss") }); Assert.IsTrue(actual); actual =
_sampleService.Create(new EfSample() { UserName = "ef" +
DateTime.Now.ToString("MMddHHmmss") }); Assert.IsTrue(actual); actual =
_sampleService.Create(new EfSample() { UserName = "ef" +
DateTime.Now.ToString("MMddHHmmss") }); Assert.IsTrue(actual); } [TestMethod()]
public void GetFirstOrDefaultTest() { EfSample actual =
_sampleService.GetFirstOrDefault(ent => ent.Id == _testId);
Assert.IsNotNull(actual); } [TestMethod()] public void GetByKeyIdTest() {
EfSample actual = _sampleService.GetByKeyId(_testId); Assert.IsNotNull(actual);
} [TestMethod()] public void GetListTest() { // ReSharper disable once
RedundantBoolCompare List<EfSample> actual = _sampleService.GetList(ent =>
ent.Available == true); Assert.IsNotNull(actual);
CollectionAssert.AllItemsAreNotNull(actual); } [TestMethod()] public void
UpdateTest() { EfSample sample = new EfSample { Id = _testId, ModifyTime =
DateTime.Now, UserName = "modify" }; bool actual =
_sampleService.Update(sample); Assert.IsNotNull(actual); } [TestMethod()]
public void TransactionSuccessTest() { EfSample sample = new EfSample {
UserName = "TransactionSuccess1" }; EfSample sample2 = new EfSample { UserName
= "TransactionSuccess2" }; bool actual =
_sampleService.CreateWithTransaction(sample, sample2); Assert.IsTrue(actual); }
[TestMethod()] public void TransactionFailTest() { EfSample sample3 = new
EfSample { UserName = "TransactionSuccess3" }; EfSample sample4 = new EfSample
{ UserName = null }; bool actual =
_sampleService.CreateWithTransaction(sample3, sample4); Assert.IsFalse(actual);
} [TestMethod()] public void ExistTest() { bool actual =
_sampleService.Exist(ent => ent.Id == _testId); Assert.IsTrue(actual); actual =
_sampleService.Exist(ent => ent.UserName == TestName); Assert.IsTrue(actual);
DateTime createTime = DateTime.Now.AddDays(-1); actual =
_sampleService.Exist(ent => ent.CreateTime >= createTime);
Assert.IsTrue(actual); actual = _sampleService.Exist(ent => ent.CreateTime <=
DateTime.Now); Assert.IsTrue(actual); // ReSharper disable once
RedundantBoolCompare actual = _sampleService.Exist(ent => ent.Available ==
true); Assert.IsTrue(actual); actual = _sampleService.Exist(ent =>
ent.Available != true); Assert.IsFalse(actual); } [TestMethod()] public void
SqlQueryTest() { string sql = @"select * from [dbo].[EFSample] where
CreateTime>=@CreateTime and Available=@Available order by CreateTime desc";
DbParameter[] parameter = { new SqlParameter(){ ParameterName="@CreateTime",
Value=DateTime.Now.AddDays(-1) }, new SqlParameter(){
ParameterName="@Available", Value=true } }; List<EfSample> actual =
_sampleService.SqlQuery(sql, parameter); Assert.IsNotNull(actual);
CollectionAssert.AllItemsAreNotNull(actual); } /// <summary> /// 多线程测试 ///
</summary> [TestMethod()] public void CreateTestThreadTest() { Task[] tasks = {
Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() =>
CreateTest()), Task.Factory.StartNew(() => CreateTest()),
Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() =>
CreateTest()), Task.Factory.StartNew(() => CreateTest()),
Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() =>
CreateTest()), Task.Factory.StartNew(() => CreateTest()),
Task.Factory.StartNew(() => CreateTest()), }; Task.WaitAll(tasks); } }
结语

* 通过上述代码,可以在项目中很方面使用Entity Framework;
* 并且很轻松实现CURD以及事务处理,从而开发中关注业务即可;
* 小弟不才,大佬轻拍;