[开源]Entity Framework 6 Repository 一种实现方式

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

插播一条求职

  1. 小弟拥有多年C#开发经验,从事过路灯,消防平台物联网平台开发,坐标上海;
  2. 如果贵司在招聘,烦请大佬考虑下,联系邮箱:[email protected]

标准仓储

/// 
/// 标准仓储接口
/// 
public interface IRepository
{
    #region Methods
 
    /// 
    /// 删除记录
    /// 
    /// 操作是否成功
    /// 需要操作的实体类.
    bool Delete(T entity) where T : ModelBase;
 
    /// 
    /// 条件判断是否存在
    /// 
    /// 是否存在
    /// 判断条件委托
    bool Exist(Expression> predicate = null) where T : ModelBase;
 
    /// 
    /// 根据id获取记录
    /// 
    /// 记录
    /// id.
    T GetByKeyId(object id) where T : ModelBase;
 
    /// 
    /// 条件获取记录集合
    /// 
    /// 集合
    /// 筛选条件.
    List GetList(Expression> predicate = null) where T : ModelBase;
 
    /// 
    /// 条件获取记录第一条或者默认
    /// 
    /// 记录
    /// 筛选条件.
    T GetFirstOrDefault(Expression> predicate = null) where T : ModelBase;
 
    /// 
    /// 创建一条记录
    /// 
    /// 操作是否成功.
    /// 实体类记录.
    bool Create(T entity) where T : ModelBase;
 
    /// 
    /// 条件查询
    /// 
    /// IQueryable
    /// 筛选条件.
    IQueryable Query(Expression> predicate = null) where T : ModelBase;
 
    /// 
    /// 根据记录
    /// 
    /// 操作是否成功.
    /// 实体类记录.
    bool Update(T entity) where T : ModelBase;
 
    #endregion Methods
}

数据访问上下文接口

public interface IDbContext : IDisposable, IRepository, IUnitOfWork
{
    /// 
    ///     执行Sql 脚本查询
    /// 
    /// Sql语句
    /// 参数
    /// 集合
    IEnumerable SqlQuery(string sql, IDbDataParameter[] parameters);
}

数据访问上下文工厂

public interface IDatabaseContextFactory
{
    /// 
    ///     Create this instance.
    /// 
    /// The create.
    IDbContext Create();
}

基于EF的DbContext

public abstract class EfDbContextBase : DbContext, IDbContext
{
    #region Constructors
 
    /// 
    ///     构造函数
    /// 
    /// dbConnection
    protected EfDbContextBase(DbConnection dbConnection)
        : base(dbConnection, true)
    {
        Configuration.LazyLoadingEnabled = false; //将不会查询到从表的数据,只会执行一次查询,可以使用 Inculde 进行手动加载;
        Configuration.ProxyCreationEnabled = false;
        Configuration.AutoDetectChangesEnabled = false;
    }
 
    #endregion Constructors
 
    #region Fields
 
    /// 
    ///     获取 是否开启事务提交
    /// 
    public virtual bool TransactionEnabled => Database.CurrentTransaction != null;
 
    #endregion Fields
 
    #region Methods
 
    /// 
    ///     显式开启数据上下文事务
    /// 
    /// 指定连接的事务锁定行为
    public void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified)
    {
        if (!TransactionEnabled) Database.BeginTransaction(isolationLevel);
    }
 
    /// 
    ///     提交当前上下文的事务更改
    /// 
    /// 提交数据更新时发生异常:" + msg
    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;
            }
    }
 
    /// 
    ///     创建记录
    /// 
    /// 操作是否成功
    /// 需要操作的实体类.
    public bool Create(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;
    }
 
    /// 
    ///     创建记录集合
    /// 
    /// 操作是否成功.
    /// 实体类集合.
    public bool Create(IEnumerable 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;
    }
 
    /// 
    ///     删除记录
    /// 
    /// 操作是否成功
    /// 需要操作的实体类.
    public bool Delete(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;
    }
 
    /// 
    ///     条件判断是否存在
    /// 
    /// 是否存在
    /// 判断条件委托
    public bool Exist(Expression> predicate = null)
        where T : ModelBase
    {
        return predicate == null ? Set().Any() : Set().Any(predicate);
    }
 
    /// 
    ///     根据id获取记录
    /// 
    /// 记录
    /// id.
    public T GetByKeyId(object id)
        where T : ModelBase
    {
        ValidateOperator.Begin().NotNull(id, "Id");
        return Set().Find(id);
    }
 
    /// 
    ///     条件获取记录集合
    /// 
    /// 集合
    /// 筛选条件.
    public List GetList(Expression> predicate = null)
        where T : ModelBase
    {
        IQueryable query = Set();
 
        if (predicate != null) query = query.Where(predicate);
 
        return query.ToList();
    }
 
    /// 
    ///     条件获取记录第一条或者默认
    /// 
    /// 记录
    /// 筛选条件.
    public T GetFirstOrDefault(Expression> predicate = null)
        where T : ModelBase
    {
        IQueryable query = Set();
 
        if (predicate != null)
            return query.FirstOrDefault(predicate);
        return query.FirstOrDefault();
    }
 
    /// 
    ///     条件查询
    /// 
    /// IQueryable
    /// 筛选条件.
    public IQueryable Query(Expression> predicate = null)
        where T : ModelBase
    {
        IQueryable query = Set();
 
        if (predicate != null) query = query.Where(predicate);
 
        return query;
    }
 
    /// 
    ///     显式回滚事务,仅在显式开启事务后有用
    /// 
    public void Rollback()
    {
        if (TransactionEnabled) Database.CurrentTransaction.Rollback();
    }
 
    /// 
    ///     执行Sql 脚本查询
    /// 
    /// Sql语句
    /// 参数
    /// 集合
    public IEnumerable SqlQuery(string sql, IDbDataParameter[] parameters)
    {
        ValidateOperator.Begin()
            .NotNullOrEmpty(sql, "Sql语句");
        // ReSharper disable once CoVariantArrayConversion
        return Database.SqlQuery(sql, parameters);
    }
 
    /// 
    ///     根据记录
    /// 
    /// 操作是否成功.
    /// 实体类记录.
    public bool Update(T entity)
        where T : ModelBase
    {
        ValidateOperator.Begin().NotNull(entity, "需要更新的数据记录");
        bool result;
        try
        {
            var set = Set();
            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();
            //if (!_sampleService.Exist(ent => ent.ID == _testID))
            //{
            //    _sampleService.Create(new EFSample() { UserName = _testName, ID = _testID });
            //}
        }
 
        /// 
        /// 创建测试
        /// 
        [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 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 actual = _sampleService.SqlQuery(sql, parameter);
            Assert.IsNotNull(actual);
            CollectionAssert.AllItemsAreNotNull(actual);
        }
 
        /// 
        /// 多线程测试
        /// 
        [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);
        }
    }

结语

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

转载于:https://www.cnblogs.com/MeetYan/p/10679158.html

你可能感兴趣的:([开源]Entity Framework 6 Repository 一种实现方式)