[开源]Entity Framework 6 Repository 一种实现方式
程序员文章站
2022-04-08 15:48:52
1. 在使用Entity Framework这种ORM框架得时候,一般结合Repository仓储形式来处理业务逻辑;虽然这种模式带来很多好处,但是也会引发一些争议,在此抛开不谈,小弟结合项目经验来实现一下,欢迎大佬拍砖; 2. 后续会带来Dapper 基于Repository实现,代码一些实现会兼 ......
- 在使用entity framework这种orm框架得时候,一般结合repository仓储形式来处理业务逻辑;虽然这种模式带来很多好处,但是也会引发一些争议,在此抛开不谈,小弟结合项目经验来实现一下,欢迎大佬拍砖;
- 后续会带来dapper 基于repository实现,代码一些实现会兼容dapper,所以做了一些比较丑陋得写法;但是我得想法是通过一些ioc可以在entity framework和dapper两者之间进行切换;
- 您可以通过nuget:install-package masterchief.dotnet.core.ef 安装使用;
- 您可以通过github:masterchief 查看具体源码以及单元测试
- 欢迎pr,欢迎star;
插播一条求职
- 小弟拥有多年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以及事务处理,从而开发中关注业务即可;
- 小弟不才,大佬轻拍;
上一篇: 微信将禁止发送这类信息 违者封号
下一篇: C# 输出字符串到文本文件中