欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-08 15:48:52
1. 在使用Entity Framework这种ORM框架得时候,一般结合Repository仓储形式来处理业务逻辑;虽然这种模式带来很多好处,但是也会引发一些争议,在此抛开不谈,小弟结合项目经验来实现一下,欢迎大佬拍砖; 2. 后续会带来Dapper 基于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. 欢迎pr,欢迎star;

插播一条求职

  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. 小弟不才,大佬轻拍;