• [开源]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. 如果贵司在招聘,烦请大佬考虑下,联系邮箱: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);
            }
        }
    

    结语

    1. 通过上述代码,可以在项目中很方面使用Entity Framework;
    2. 并且很轻松实现CURD以及事务处理,从而开发中关注业务即可;
    3. 小弟不才,大佬轻拍;
  • 相关阅读:
    从零开始学安全(三十五)●mysql 盲注手工自定义python脚本
    从零开始学安全(三十四)●百度杯 ctf比赛 九月场 sqli
    从零开始学安全(三十三)●Ununtu16 LMAP 环境搭建
    从零开始学安全(三十二)●各种编码总结
    从零开始学安全(三十一)●kali 输入 msfconsole 启动报错
    从零开始学安全(三十)●使用sqlmap对网站一步步渗透
    从零开始学安全(二十九)●上传漏洞代码分析
    从零开始学安全(二十八)●中国菜刀各模块使用详解
    从零开始学安全(二十七)●利用Nmap对防火墙,IDS,IPS 进行欺骗
    如何获取SAP_ALL权限 的代码(还没测试转自SAP翔子)
  • 原文地址:https://www.cnblogs.com/MeetYan/p/10679158.html
Copyright © 2020-2023  润新知