首页后端开发ASP.NET总结EF通用数据层封装类实例详解

总结EF通用数据层封装类实例详解

时间2024-01-30 05:58:03发布访客分类ASP.NET浏览562
导读:收集整理的这篇文章主要介绍了总结EF通用数据层封装类实例详解,觉得挺不错的,现在分享给大家,也给大家做个参考。浅谈orm 记得四年前在学校第一次接触到 Ling to SQL,那时候瞬间发现不用手写sql语句是多么的方便,后面慢慢的接触了...
收集整理的这篇文章主要介绍了总结EF通用数据层封装类实例详解,觉得挺不错的,现在分享给大家,也给大家做个参考。

浅谈orm

  记得四年前在学校第一次接触到 Ling to SQL,那时候瞬间发现不用手写sql语句是多么的方便,后面慢慢的接触了许多orm框架,像 EF,DapPEr,Hibernate,ServiceStack.OrMLITe 等。当然每种orm都有各自的优势,也有不足的地方。园子里也有很多大神开源了他们写的orm,如SqlSugar,Chloe.ORM,CYQ.Data 等。先不说这些开源的orm使用度怎么样,我觉得起码从开源的精神上就很可嘉了,我也曾下载过这几位大神的源码进行学习。
  所有orm最终体现的一点就是方便,减少程序员重复性的工作,当然目前还有一些公司还是使用手写sql的方式来做,我觉得整个项目都使用手写sql来做真的是有点闲到蛋疼,并不是不推荐手写sql的方式,只是个人觉得最基本的增删改查这些都手写的话,那其实考验不是能力,而是耐力。有人说手写sql的方式可控性强,性能高,我想说的是orm也能做到,关键是你怎么去使用。
  orm的优点非常明显,开发便捷,但或许也是由于这个优点,让很多偷懒的程序员也会渐渐忘了sql语句的写法,我遇到过很多的程序员朋友用了EF后,手写sql,视图、存储过程这些都不想用了,我个人觉手写sql这种还是必要的。不然某一天你看到别人的程序里面写着 “exec xxxx”,你就会突然觉得“啊,好像在哪里见过.....”。所以我想说的是“该出手时还是得出手"。

浅谈Entity Framework

  Entity Framework 是微软家的orm框架,随着 Entity Framework 不断的完善强化,目前相信使用的比例相对其他的orm来说还是较高的。像我目前使用的最多的就是EF和Dapper。确实,EF用起来开发过程中会方便很多,毕竟EF走过了这么年头,无论是成熟度,还是性能等都提高了很多,也有很多开发者为EF提供了扩展功能,如entity framework extended 等。而且作为.net开发者来说项目通用性也很强,资料也多,微软在这块的更新力度也很给力。不过之前刚出的EF Core也存在一些坑,毕竟还是初期阶段,相信现在后面会越来越好的。

  Entity Framework 提供了三种开发模式,code First,db first,model first。目前用的最多的就属code first了。至于这三种模式的简单使用和区别,大家可以参考下这篇文章。

  我曾听一些朋友说过说EF使用起来性能很差,生成的sql语句很难看等。我觉得说这种话之前还是先检查下代码或者多看下一些EF文章吧,要先确保自己没给自己挖坑,然后才能指责别人的不好。如果真心觉得EF或者其他的orm用起来很不爽,那就自己写一个吧,我也曾经和同事用Dapper扩展一个通用的orm,当时是出于一种学习和使用方便的角度。

Entity Framework 通用数据层类

  这里提供下 EF 通用数据层父类方法,其实网上也有很多人提供了自己项目中的 EF 通用数据层父类方法,所以这里提供的并不是最优和最好的选择,只能说是可以通用的类,方便大家学习和使用,具体代码如下:

DbContextFactory DbContext工厂类

    public class DbContextFactory    {
public  DbContext GetDbContext()        {
    string key = typeof(DBContext.DbContextFactory).Name + "XJHDbContext";
                DbContext dbContext = CallContext.GetData(key) as DbContext;
if (dbContext == null)            {
                    dbContext = new XJHDbContext();
                    CallContext.SetData(key, dbContext);
            }
    return dbContext;
        }
    }
    

DbBase 数据层通用操作类

 public class DbBase    {
    PRotected DbContext Db = new DbContextFactory().GetDbContext();
            #region 自定义其他方法/// summary>
    /// 执行存储过程或自定义sql语句--返回集合(自定义返回类型)/// /summary>
    /// param name="sql">
    /param>
    /// param name="parms">
    /param>
    /// param name="cmdType">
    /param>
    /// returns>
    /returns>
    public ListTModel>
     QueryTModel>
    (string sql, ListSqlParameter>
 parms, CommandType cmdType = CommandType.Text)        {
//存储过程(exec getActionUrlId @name,@ID)if (cmdType == CommandType.StoredProcedure)            {
                    StringBuilder paranames = new StringBuilder();
foreach (VAR sqlPara in parms)                {
                    paraNames.Append($" @{
sqlPara}
    ,");
                }
                    sql = paraNames.Length >
 0 ? $"exec {
sql}
 {
paraNames.ToString().Trim(',')}
" : $"exec {
sql}
     ";
            }
    var list = Db.Database.SqlQueryTModel>
    (sql, parms.ToArray());
    var enityList = list.ToList();
    return enityList;
        }
    /// summary>
    /// 自定义语句和存储过程的增删改--返回影响的行数/// /summary>
    /// param name="sql">
    /param>
    /// param name="parms">
    /param>
    /// param name="cmdType">
    /param>
    /// returns>
    /returns>
    public int Execute(string sql, ListSqlParameter>
 parms, CommandType cmdType = CommandType.Text)        {
//存储过程(exec getActionUrlId @name,@ID)if (cmdType == CommandType.StoredProcedure)            {
                    StringBuilder paraNames = new StringBuilder();
foreach (var sqlPara in parms)                {
                    paraNames.Append($" @{
sqlPara}
    ,");
                }
                    sql = paraNames.Length >
 0 ?$"exec {
sql}
 {
paraNames.ToString().Trim(',')}
" :                    $"exec {
sql}
     ";
            }
    int ret = Db.Database.ExecuteSqlCommand(sql, parms.ToArray());
    return ret;
        }
#endregion 自定义其他方法}
    /// summary>
    /// mssql数据库 数据层 父类/// /summary>
    /// typeparam name="T">
    /typeparam>
    public class DbBaseT>
 : DbBase where T : class, new()    {
    #region INSERT/// summary>
    /// 新增 实体/// /summary>
    /// param name="model">
    /param>
    /// returns>
    /returns>
public void Insert(T model)        {
                Db.SetT>
    ().Add(model);
        }
    /// summary>
    /// 普通批量插入/// /summary>
    /// param name="datas">
    /param>
    public void InsertRange(ListT>
 datas)        {
                Db.SetT>
    ().AddRange(datas);
        }
    #endregion INSERT#region DELETE/// summary>
    /// 根据模型删除/// /summary>
    /// param name="model">
    包含要删除id的对象/param>
    /// returns>
    /returns>
public void Delete(T model)        {
                Db.SetT>
    ().Attach(model);
                Db.SetT>
    ().Remove(model);
        }
    /// summary>
    /// 删除/// /summary>
    /// param name="whereLambda">
    /param>
    public void Delete(ExPressionFuncT, bool>
    >
 whereLambda)        {
                Db.SetT>
    ().Where(whereLambda).Delete();
        }
    #endregion DELETE#region UPDATE/// summary>
    /// 单个对象指定列修改/// /summary>
    /// param name="model">
    要修改的实体对象/param>
    /// param name="proNames">
    要修改的 属性 名称/param>
    /// param name="isProUpdate">
    /param>
    /// returns>
    /returns>
    public void Update(T model, Liststring>
 proNames, bool isProUpdate = true)        {
    //将 对象 添加到 EF中Db.SetT>
    ().Attach(model);
    var setEntry = ((IObjectContextAdapter)Db).ObjectContext.ObjectstateManager.GetObjectStateEntry(model);
//指定列修改if (isProUpdate)            {
foreach (string proName in proNames)                {
                        setEntry.SetModifiedProperty(proName);
                }
            }
//忽略类修改else{
                    Type t = typeof(T);
                    ListPropertyInfo>
     pROInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
foreach (var item in proInfos)                {
    string proName = item.Name;
if (proNames.Contains(proName))                    {
    continue;
                    }
                        setEntry.SetModifiedProperty(proName);
                }
            }
        }
    /// summary>
    /// 单个对象修改/// /summary>
    /// param name="model">
    /param>
    /// returns>
    /returns>
public void Update(T model)        {
                DbEntityEntry entry = Db.EntryT>
    (model);
                Db.SetT>
    ().Attach(model);
                entry.State = EntityState.Modified;
        }
    /// summary>
    /// 批量修改/// /summary>
    /// param name="whereLambda">
    /param>
    /// param name="updateExpression">
    /param>
    public void Update(ExpressionFuncT, bool>
    >
     whereLambda, ExpressionFuncT, T>
    >
 updateExpression)        {
                Db.SetT>
    ().Where(whereLambda).Update(updateExpression);
        }
    /// summary>
    /// 批量修改/// /summary>
    /// param name="models">
    /param>
    /// returns>
    /returns>
    public void UpdateAll(ListT>
 models)        {
foreach (var model in models)            {
                    DbEntityEntry entry = Db.Entry(model);
                    entry.State = EntityState.Modified;
            }
        }
    /// summary>
    /// 批量统一修改/// /summary>
    /// param name="model">
    要修改的实体对象/param>
    /// param name="whereLambda">
    查询条件/param>
    /// param name="modifiedProNames">
    /param>
    /// returns>
    /returns>
    public void Update(T model, ExpressionFuncT, bool>
    >
 whereLambda, params string[] modifiedProNames)        {
    //查询要修改的数据ListT>
     listModifing = Db.SetT>
    ().Where(whereLambda).ToList();
                Type t = typeof(T);
                ListPropertyInfo>
     proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
                Dictionarystring, PropertyInfo>
     dictPros = new Dictionarystring, PropertyInfo>
    ();
                proInfos.ForEach(p =>
{
if (modifiedProNames.Contains(p.Name))                {
                        dictPros.Add(p.Name, p);
                }
            }
    );
if (dictPros.Count = 0)            {
    throw new Exception("指定修改的字段名称有误或为空");
            }
foreach (var item in dictPros)            {
                    PropertyInfo proInfo = item.Value;
    //取出 要修改的值object newValue = proInfo.GetValue(model, null);
//批量设置 要修改 对象的 属性foreach (T oModel in listModifing)                {
    //为 要修改的对象 的 要修改的属性 设置新的值proInfo.SetValue(oModel, newValue, null);
                }
            }
        }
    #endregion UPDATE#region SELECT/// summary>
    /// 根据主键查询/// /summary>
    /// param name="id">
    /param>
    /// returns>
    /returns>
public T FindById(dynamic id)        {
    return Db.SetT>
    ().Find(id);
        }
    /// summary>
    /// 获取默认一条数据,没有则为NULL/// /summary>
    /// param name="whereLambda">
    /param>
    /// returns>
    /returns>
    public T FirstOrDefault(ExpressionFuncT, bool>
    >
 whereLambda = null)        {
if (whereLambda == null)            {
    return Db.SetT>
    ().FirstOrDefault();
            }
    return Db.SetT>
    ().FirstOrDefault(whereLambda);
        }
    /// summary>
    /// 获取全部数据/// /summary>
    /// returns>
    /returns>
    public ListT>
 GetAll(string ordering = null)        {
    return ordering == null? Db.SetT>
    ().ToList()                : Db.SetT>
    ().OrderBy(ordering).ToList();
        }
    /// summary>
    /// 带条件查询获取数据/// /summary>
    /// param name="whereLambda">
    /param>
    /// param name="ordering">
    /param>
    /// returns>
    /returns>
    public ListT>
     GetAll(ExpressionFuncT, bool>
    >
 whereLambda, string ordering = null)        {
    var iQueryable = Db.SetT>
    ().Where(whereLambda);
    return ordering == null? iQueryable.ToList()                : iQueryable.OrderBy(ordering).ToList();
        }
    /// summary>
    /// 带条件查询获取数据/// /summary>
    /// param name="whereLambda">
    /param>
    /// returns>
    /returns>
    public IQueryableT>
     GetAllIQueryable(ExpressionFuncT, bool>
    >
 whereLambda = null)        {
    return whereLambda == null ? Db.SetT>
    () : Db.SetT>
    ().Where(whereLambda);
        }
    /// summary>
    /// 获取数量/// /summary>
    /// param name="whereLambd">
    /param>
    /// returns>
    /returns>
    public int GetCount(ExpressionFuncT, bool>
    >
 whereLambd = null)        {
    return whereLambd == null ? Db.SetT>
    ().Count() : Db.SetT>
    ().Where(whereLambd).Count();
        }
    /// summary>
    /// 判断对象是否存在/// /summary>
    /// param name="whereLambd">
    /param>
    /// returns>
    /returns>
    public bool Any(ExpressionFuncT, bool>
    >
 whereLambd)        {
    return Db.SetT>
    ().Where(whereLambd).Any();
        }
    /// summary>
    /// 分页查询/// /summary>
    /// param name="pageindex">
    当前页码/param>
    /// param name="pageSize">
    每页大小/param>
    /// param name="rows">
    总条数/param>
    /// param name="orderBy">
    排序条件(一定要有)/param>
    /// param name="whereLambda">
    查询添加(可有,可无)/param>
    /// param name="isOrder">
    是否是Order排序/param>
    /// returns>
    /returns>
    public ListT>
     PageTKey>
    (int pageIndex, int pageSize, out int rows, ExpressionFuncT, TKey>
    >
     orderBy, ExpressionFuncT, bool>
    >
 whereLambda = null, bool isOrder = true)        {
                IQueryableT>
     data = isOrder ?Db.SetT>
    ().OrderBy(orderBy) :                Db.SetT>
    ().OrderByDescending(orderBy);
if (whereLambda != null)            {
                    data = data.Where(whereLambda);
            }
                rows = data.Count();
    return data.PageBy((pageIndex - 1) * pageSize, pageSize).ToList();
        }
    /// summary>
    /// 分页查询/// /summary>
    /// param name="pageIndex">
    当前页码/param>
    /// param name="pageSize">
    每页大小/param>
    /// param name="rows">
    总条数/param>
    /// param name="ordering">
    排序条件(一定要有)/param>
    /// param name="whereLambda">
    查询添加(可有,可无)/param>
    /// returns>
    /returns>
    public ListT>
     Page(int pageIndex, int pageSize, out int rows, string ordering, ExpressionFuncT, bool>
    >
 whereLambda = null)        {
    // 分页 一定注意: Skip 之前一定要 OrderByvar data = Db.SetT>
    ().OrderBy(ordering);
if (whereLambda != null)            {
                    data = data.Where(whereLambda);
            }
                rows = data.Count();
    return data.PageBy((pageIndex - 1) * pageSize, pageSize).ToList();
        }
    /// summary>
    /// 查询转换/// /summary>
    /// typeparam name="TDto">
    /typeparam>
    /// param name="whereLambda">
    /param>
    /// returns>
    /returns>
    public ListTDto>
     SelectTDto>
    (ExpressionFuncT, bool>
    >
 whereLambda)        {
    return Db.SetT>
    ().Where(whereLambda).SelectTDto>
    ().ToList();
        }
    #endregion SELECT#region ORTHER/// summary>
    /// 执行存储过程或自定义sql语句--返回集合/// /summary>
    /// param name="sql">
    /param>
    /// param name="parms">
    /param>
    /// param name="cmdType">
    /param>
    /// returns>
    /returns>
    public ListT>
     Query(string sql, ListSqlParameter>
 parms, CommandType cmdType = CommandType.Text)        {
    return QueryT>
    (sql, parms, cmdType);
        }
    /// summary>
    /// 提交保存/// /summary>
    /// returns>
    /returns>
public int SaveChanges()        {
    return Db.SaveChanges();
        }
    /// summary>
    /// 回滚/// /summary>
public void RollBackChanges()        {
    var items = Db.ChangeTracker.Entries().ToList();
                items.ForEach(o =>
     o.State = EntityState.Unchanged);
        }
#endregion ORTHER}
    
DbBase

扩展类,实现读写分离

  上面的通用类是比较基础简单通用的,适合于单库读写操作。对于EF实现读写分离,之前网上找过类似的参考文章,很多人文章都是使用 DbCommandInterceptor拦截器 来实现,具体的做法是通过拦截到sql语句,然后根据具体条件去判断是走主库还是从库。这种做法不是不行,只是个人感觉不是很好扩展,而且要在拦截器里面做限制判断。

  其实说白了EF本身就是一个读写分离的orm。用过EF的人知道,EF提供访问数据库的是 DbContext 这个对象,所以想实现读写分离的就很简单了,只要在程序中使用两个不同的DbContext对象,一个负责读,一个负责写就好了。

  所以在上面提供的通用封装类中稍微做下修改,修改如下DbContextFactory中获取DbContext的方法,实现一个读的DbContext和一个写的DbContext对象的获取。

  这里要注意下,对于读的DbContext来说,要做下设置
  1.使用 Database.SetInitializer(new NullDatabaseInitializerReadDbContext> ()); 改变ef初始化策略,因为一般我们使用读写分离的话从库都是同步于主库的,所以不使用ef的自动创建数据库策略。
  2.重写 SaveChanges 方法,对应从库来说,只提供读取的功能,所以防止误操作,这里禁用掉SaveChanges方法,一般需要使用从读的保存方法,就对外抛出异常。

  代码如下:

支持读写分离的 DbContextFactory 类

  public class DbContextFactory    {
public DbContext GetWriteDbContext(){
    string key = typeof(DbContextFactory).Name + "WriteDbContext";
                DbContext dbContext = CallContext.GetData(key) as DbContext;
if (dbContext == null)            {
                    dbContext = new WriteDbContext();
                    CallContext.SetData(key, dbContext);
            }
    return dbContext;
        }
public DbContext GetReadDbContext(){
    string key = typeof(DbContextFactory).Name + "ReadDbContext";
                DbContext dbContext = CallContext.GetData(key) as DbContext;
if (dbContext == null)            {
                    dbContext = new ReadDbContext();
                    CallContext.SetData(key, dbContext);
            }
    return dbContext;
        }
    }
    

对应的 DbBase 类也做下修改,主要将上面的Db对象改作 MasterDb SlaveDb 对象,并且把上面的读写方法坐下调整,修改后如下:

支持读写分离的 DbBase类

public class DbBase    {
    //是否读写分离(可以配置在配置文件中)private static readonly bool IsReadWriteSeparation = true;
    #region EF上下文对象(主库)protected DbContext MasterDb =>
     _masterDb.Value;
    private readonly LazyDbContext>
     _masterDb = new LazyDbContext>
    (() =>
     new DbContextFactory().GetWriteDbContext());
    #endregion EF上下文对象(主库)#region EF上下文对象(从库)protected DbContext SlaveDb =>
     IsReadWriteSeparation ? _slaveDb.Value : _masterDb.Value;
    private readonly LazyDbContext>
     _slaveDb = new LazyDbContext>
    (() =>
     new DbContextFactory().GetReadDbContext());
    #endregion EF上下文对象(从库)#region 自定义其他方法/// summary>
    /// 执行存储过程或自定义sql语句--返回集合(自定义返回类型)/// /summary>
    /// param name="sql">
    /param>
    /// param name="parms">
    /param>
    /// param name="cmdType">
    /param>
    /// returns>
    /returns>
    public ListTModel>
     QueryTModel>
    (string sql, ListSqlParameter>
 parms, CommandType cmdType = CommandType.Text)        {
//存储过程(exec getActionUrlId @name,@ID)if (cmdType == CommandType.StoredProcedure)            {
                    StringBuilder paraNames = new StringBuilder();
foreach (var sqlPara in parms)                {
                    paraNames.Append($" @{
sqlPara}
    ,");
                }
                    sql = paraNames.Length >
 0 ? $"exec {
sql}
 {
paraNames.ToString().Trim(',')}
" : $"exec {
sql}
     ";
            }
    var list = SlaveDb.Database.SqlQueryTModel>
    (sql, parms.ToArray());
    var enityList = list.ToList();
    return enityList;
        }
    /// summary>
    /// 自定义语句和存储过程的增删改--返回影响的行数/// /summary>
    /// param name="sql">
    /param>
    /// param name="parms">
    /param>
    /// param name="cmdType">
    /param>
    /// returns>
    /returns>
    public int Execute(string sql, ListSqlParameter>
 parms, CommandType cmdType = CommandType.Text)        {
//存储过程(exec getActionUrlId @name,@ID)if (cmdType == CommandType.StoredProcedure)            {
                    StringBuilder paraNames = new StringBuilder();
foreach (var sqlPara in parms)                {
                    paraNames.Append($" @{
sqlPara}
    ,");
                }
                    sql = paraNames.Length >
 0 ?$"exec {
sql}
 {
paraNames.ToString().Trim(',')}
" :                    $"exec {
sql}
     ";
            }
    int ret = MasterDb.Database.ExecuteSqlCommand(sql, parms.ToArray());
    return ret;
        }
#endregion 自定义其他方法}
    /// summary>
    /// mssql数据库 数据层 父类/// /summary>
    /// typeparam name="T">
    /typeparam>
    public class DbBaseT>
 : DbBase where T : class, new()    {
    #region INSERT/// summary>
    /// 新增 实体/// /summary>
    /// param name="model">
    /param>
    /// returns>
    /returns>
public void Insert(T model)        {
                MasterDb.SetT>
    ().Add(model);
        }
    /// summary>
    /// 普通批量插入/// /summary>
    /// param name="datas">
    /param>
    public void InsertRange(ListT>
 datas)        {
                MasterDb.SetT>
    ().AddRange(datas);
        }
    #endregion INSERT#region DELETE/// summary>
    /// 根据模型删除/// /summary>
    /// param name="model">
    包含要删除id的对象/param>
    /// returns>
    /returns>
public void Delete(T model)        {
                MasterDb.SetT>
    ().Attach(model);
                MasterDb.SetT>
    ().Remove(model);
        }
    /// summary>
    /// 删除/// /summary>
    /// param name="whereLambda">
    /param>
    public void Delete(ExpressionFuncT, bool>
    >
 whereLambda)        {
                MasterDb.SetT>
    ().Where(whereLambda).Delete();
        }
    #endregion DELETE#region UPDATE/// summary>
    /// 单个对象指定列修改/// /summary>
    /// param name="model">
    要修改的实体对象/param>
    /// param name="proNames">
    要修改的 属性 名称/param>
    /// param name="isProUpdate">
    /param>
    /// returns>
    /returns>
    public void Update(T model, Liststring>
 proNames, bool isProUpdate = true)        {
    //将 对象 添加到 EF中MasterDb.SetT>
    ().Attach(model);
    var setEntry = ((IObjectContextAdapter)MasterDb).ObjectContext.ObjectStateManager.GetObjectStateEntry(model);
//指定列修改if (isProUpdate)            {
foreach (string proName in proNames)                {
                        setEntry.SetModifiedProperty(proName);
                }
            }
//忽略类修改else{
                    Type t = typeof(T);
                    ListPropertyInfo>
     proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
foreach (var item in proInfos)                {
    string proName = item.Name;
if (proNames.Contains(proName))                    {
    continue;
                    }
                        setEntry.SetModifiedProperty(proName);
                }
            }
        }
    /// summary>
    /// 单个对象修改/// /summary>
    /// param name="model">
    /param>
    /// returns>
    /returns>
public void Update(T model)        {
                DbEntityEntry entry = MasterDb.EntryT>
    (model);
                MasterDb.SetT>
    ().Attach(model);
                entry.State = EntityState.Modified;
        }
    /// summary>
    /// 批量修改/// /summary>
    /// param name="whereLambda">
    /param>
    /// param name="updateExpression">
    /param>
    public void Update(ExpressionFuncT, bool>
    >
     whereLambda, ExpressionFuncT, T>
    >
 updateExpression)        {
                MasterDb.SetT>
    ().Where(whereLambda).Update(updateExpression);
        }
    /// summary>
    /// 批量修改/// /summary>
    /// param name="models">
    /param>
    /// returns>
    /returns>
    public void UpdateAll(ListT>
 models)        {
foreach (var model in models)            {
                    DbEntityEntry entry = MasterDb.Entry(model);
                    entry.State = EntityState.Modified;
            }
        }
    /// summary>
    /// 批量统一修改/// /summary>
    /// param name="model">
    要修改的实体对象/param>
    /// param name="whereLambda">
    查询条件/param>
    /// param name="modifiedProNames">
    /param>
    /// returns>
    /returns>
    public void Update(T model, ExpressionFuncT, bool>
    >
 whereLambda, params string[] modifiedProNames)        {
    //查询要修改的数据ListT>
     listModifing = MasterDb.SetT>
    ().Where(whereLambda).ToList();
                Type t = typeof(T);
                ListPropertyInfo>
     proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
                Dictionarystring, PropertyInfo>
     dictPros = new Dictionarystring, PropertyInfo>
    ();
                proInfos.ForEach(p =>
{
if (modifiedProNames.Contains(p.Name))                {
                        dictPros.Add(p.Name, p);
                }
            }
    );
if (dictPros.Count = 0)            {
    throw new Exception("指定修改的字段名称有误或为空");
            }
foreach (var item in dictPros)            {
                    PropertyInfo proInfo = item.Value;
    //取出 要修改的值object newValue = proInfo.GetValue(model, null);
//批量设置 要修改 对象的 属性foreach (T oModel in listModifing)                {
    //为 要修改的对象 的 要修改的属性 设置新的值proInfo.SetValue(oModel, newValue, null);
                }
            }
        }
    #endregion UPDATE#region SELECT/// summary>
    /// 根据主键查询/// /summary>
    /// param name="id">
    /param>
    /// returns>
    /returns>
public T FindById(dynamic id)        {
    return SlaveDb.SetT>
    ().Find(id);
        }
    /// summary>
    /// 获取默认一条数据,没有则为NULL/// /summary>
    /// param name="whereLambda">
    /param>
    /// returns>
    /returns>
    public T FirstOrDefault(ExpressionFuncT, bool>
    >
 whereLambda = null)        {
if (whereLambda == null)            {
    return SlaveDb.SetT>
    ().FirstOrDefault();
            }
    return SlaveDb.SetT>
    ().FirstOrDefault(whereLambda);
        }
    /// summary>
    /// 获取全部数据/// /summary>
    /// returns>
    /returns>
    public ListT>
 GetAll(string ordering = null)        {
    return ordering == null? SlaveDb.SetT>
    ().ToList()                : SlaveDb.SetT>
    ().OrderBy(ordering).ToList();
        }
    /// summary>
    /// 带条件查询获取数据/// /summary>
    /// param name="whereLambda">
    /param>
    /// param name="ordering">
    /param>
    /// returns>
    /returns>
    public ListT>
     GetAll(ExpressionFuncT, bool>
    >
 whereLambda, string ordering = null)        {
    var iQueryable = SlaveDb.SetT>
    ().Where(whereLambda);
    return ordering == null? iQueryable.ToList()                : iQueryable.OrderBy(ordering).ToList();
        }
    /// summary>
    /// 带条件查询获取数据/// /summary>
    /// param name="whereLambda">
    /param>
    /// returns>
    /returns>
    public IQueryableT>
     GetAllIQueryable(ExpressionFuncT, bool>
    >
 whereLambda = null)        {
    return whereLambda == null ? SlaveDb.SetT>
    () : SlaveDb.SetT>
    ().Where(whereLambda);
        }
    /// summary>
    /// 获取数量/// /summary>
    /// param name="whereLambd">
    /param>
    /// returns>
    /returns>
    public int GetCount(ExpressionFuncT, bool>
    >
 whereLambd = null)        {
    return whereLambd == null ? SlaveDb.SetT>
    ().Count() : SlaveDb.SetT>
    ().Where(whereLambd).Count();
        }
    /// summary>
    /// 判断对象是否存在/// /summary>
    /// param name="whereLambd">
    /param>
    /// returns>
    /returns>
    public bool Any(ExpressionFuncT, bool>
    >
 whereLambd)        {
    return SlaveDb.SetT>
    ().Where(whereLambd).Any();
        }
    /// summary>
    /// 分页查询/// /summary>
    /// param name="pageIndex">
    当前页码/param>
    /// param name="pageSize">
    每页大小/param>
    /// param name="rows">
    总条数/param>
    /// param name="orderBy">
    排序条件(一定要有)/param>
    /// param name="whereLambda">
    查询添加(可有,可无)/param>
    /// param name="isOrder">
    是否是Order排序/param>
    /// returns>
    /returns>
    public ListT>
     PageTKey>
    (int pageIndex, int pageSize, out int rows, ExpressionFuncT, TKey>
    >
     orderBy, ExpressionFuncT, bool>
    >
 whereLambda = null, bool isOrder = true)        {
                IQueryableT>
     data = isOrder ?SlaveDb.SetT>
    ().OrderBy(orderBy) :                SlaveDb.SetT>
    ().OrderByDescending(orderBy);
if (whereLambda != null)            {
                    data = data.Where(whereLambda);
            }
                rows = data.Count();
    return data.PageBy((pageIndex - 1) * pageSize, pageSize).ToList();
        }
    /// summary>
    /// 分页查询/// /summary>
    /// param name="pageIndex">
    当前页码/param>
    /// param name="pageSize">
    每页大小/param>
    /// param name="rows">
    总条数/param>
    /// param name="ordering">
    排序条件(一定要有)/param>
    /// param name="whereLambda">
    查询添加(可有,可无)/param>
    /// returns>
    /returns>
    public ListT>
     Page(int pageIndex, int pageSize, out int rows, string ordering, ExpressionFuncT, bool>
    >
 whereLambda = null)        {
    // 分页 一定注意: Skip 之前一定要 OrderByvar data = SlaveDb.SetT>
    ().OrderBy(ordering);
if (whereLambda != null)            {
                    data = data.Where(whereLambda);
            }
                rows = data.Count();
    return data.PageBy((pageIndex - 1) * pageSize, pageSize).ToList();
        }
    /// summary>
    /// 查询转换/// /summary>
    /// typeparam name="TDto">
    /typeparam>
    /// param name="whereLambda">
    /param>
    /// returns>
    /returns>
    public ListTDto>
     SelectTDto>
    (ExpressionFuncT, bool>
    >
 whereLambda)        {
    return SlaveDb.SetT>
    ().Where(whereLambda).SelectTDto>
    ().ToList();
        }
    #endregion SELECT#region ORTHER/// summary>
    /// 执行存储过程或自定义sql语句--返回集合/// /summary>
    /// param name="sql">
    /param>
    /// param name="parms">
    /param>
    /// param name="cmdType">
    /param>
    /// returns>
    /returns>
    public ListT>
     Query(string sql, ListSqlParameter>
 parms, CommandType cmdType = CommandType.Text)        {
    return QueryT>
    (sql, parms, cmdType);
        }
    /// summary>
    /// 提交保存/// /summary>
    /// returns>
    /returns>
public int SaveChanges()        {
    return MasterDb.SaveChanges();
        }
    /// summary>
    /// 回滚/// /summary>
public void RollBackChanges()        {
    var items = MasterDb.ChangeTracker.Entries().ToList();
                items.ForEach(o =>
     o.State = EntityState.Unchanged);
        }
#endregion ORTHER}
    
DbBase

  这样简单的读写分离就实现了,实现逻辑也比较清晰,方便扩展。

进一步改造,实现多从库读取

  一般做读写分离,都会做一主多从,特别对读取量比较大的项目,这样多库读取就能减轻读库的压力。所以对于上面的方法,做下改造。
  上面可以看到,主库和从库都是通过 DbContextFactory 这个类来获取的,在GetReadDbContext 方法中每次都是获取 ReadDbContext 这个对象。那么对于多个从库的情况下,每次读取到底要去哪个库读取数据呢?这里就是一个算法规则的问题了,或者说是策略吧,如果使用过nginx的朋友就知道,nginx本身内部在实现负载均衡的时候提供了多种策略,比如轮询,加权轮询,ip_hash等策略。其实上面获取同一个ReadDbContext 的方法也算一种策略,叫单一策略,每次都获取单一的对象。

  多从库的情况下,我们简单的来实现另一种获取策略,随机策略,每次都随机获取到一个从库的对象,这种是最简单的策略,当然,正式使用的话大家可以发挥自己的创造力,写出多了的算法策略。

首先,定义一个策略接口,方便策略的扩展和切换,代码如下:

IReadDbStrategy 接口

 /// summary>
      /// 从数据库获取策略接口  /// /summary>
  public interface IReadDbStrategy  {
          /// summary>
      /// 获取读库      /// /summary>
      /// returns>
    /returns>
          DbContext GetDbContext();
  }
    

单从库情况下,定义一个单一策略,代码如下:

单一策略

   /// summary>
       /// 单一策略   /// /summary>
   public class SingleStrategy : IReadDbStrategy   {
       public DbContext GetDbContext()       {
               return new ReadDbContext();
       }
   }
    

多从库情况下,定义一个随机策略,代码如下:

随机策略

    /// summary>
    /// 随机策略/// /summary>
public class RandomStrategy : IReadDbStrategy    {
    //所有读库类型public static ListType>
     DBTypes;
 static RandomStrategy()        {
                LoadDbs();
        }
 //加载所有的读库类型static void LoadDbs()        {
                DbTypes = new ListType>
    ();
    var asSEMbly = Assembly.GetExecutingAssembly();
    var types = assembly.GetTypes();
foreach (var type in types)            {
if (type.BaseType == typeof(BaseReadDbContext))                {
                        DbTypes.Add(type);
                }
            }
        }
 public DbContext GetDbContext()        {
    int randomIndex = new Random().Next(0, DbTypes.Count);
    var dbType = DbTypes[randomIndex];
    var dbContext = Activator.CreateInstance(dbType) as DbContext;
    return dbContext;
        }
    }
    

  这样,所有从库我们都基于策略去获取,扩展也比较方便。修改下 DbContextFactory 类的 GetReadDbContext 方法,通过策略接口来获取,代码如下:

支持一主多从的 DbContextFactory 类

  public class DbContextFactory    {
    //todo:这里可以自己通过注入的方式来实现,就会更加灵活private static readonly IReadDbStrategy ReadDbStrategy = new RandomStrategy();
public DbContext GetWriteDbContext()        {
    string key = typeof(DbContextFactory).Name + "WriteDbContext";
                DbContext dbContext = CallContext.GetData(key) as DbContext;
if (dbContext == null)            {
                    dbContext = new WriteDbContext();
                    CallContext.SetData(key, dbContext);
            }
    return dbContext;
        }
public DbContext GetReadDbContext()        {
    string key = typeof(DbContextFactory).Name + "ReadDbContext";
                DbContext dbContext = CallContext.GetData(key) as DbContext;
if (dbContext == null)            {
                    dbContext = ReadDbStrategy.GetDbContext();
    CallContext.SetData(key, dbContext);
            }
    return dbContext;
        }
    }
    

  这样简单的一主多从也实现了。

参考文章

  
  

源码分享

  所有的代码提供给大家的更多的是一种思路和学习的参考,如果有什么不足的地方也欢迎大家批评指正,如果觉得对你有帮助,不要吝啬你的鼠标,帮忙点个星,点个赞吧。

以上就是总结EF通用数据层封装类实例详解的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

封装支持数据读写

若转载请注明出处: 总结EF通用数据层封装类实例详解
本文地址: https://pptw.com/jishu/592130.html
C#中foreach实例代码 浅析JS中base64和图片互相转换(附代码)

游客 回复需填写必要信息