EF通用數據層封裝類(支持讀寫分離,一主多從)

来源:http://www.cnblogs.com/qtqq/archive/2017/06/04/6942312.html
-Advertisement-
Play Games

淺談orm 記得四年前在學校第一次接觸到 Ling to Sql,那時候瞬間發現不用手寫sql語句是多麼的方便,後面慢慢的接觸了許多orm框架,像 EF,Dapper,Hibernate,ServiceStack.OrmLite 等。當然每種orm都有各自的優勢,也有不足的地方。園子里也有很多大神開 ...


淺談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 List<TModel> Query<TModel>(string sql, List<SqlParameter> 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.SqlQuery<TModel>(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, List<SqlParameter> 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 DbBase<T> : DbBase where T : class, new()
    {
        #region INSERT

        /// <summary>
        /// 新增 實體
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void Insert(T model)
        {
            Db.Set<T>().Add(model);

        }

        /// <summary>
        /// 普通批量插入
        /// </summary>
        /// <param name="datas"></param>
        public void InsertRange(List<T> datas)
        {
            Db.Set<T>().AddRange(datas);
        }

        #endregion INSERT

        #region DELETE

        /// <summary>
        /// 根據模型刪除
        /// </summary>
        /// <param name="model">包含要刪除id的對象</param>
        /// <returns></returns>
        public void Delete(T model)
        {
            Db.Set<T>().Attach(model);
            Db.Set<T>().Remove(model);
        }

        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="whereLambda"></param>
        public void Delete(Expression<Func<T, bool>> whereLambda)
        {
            Db.Set<T>().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, List<string> proNames, bool isProUpdate = true)
        {
            //將 對象 添加到 EF中
            Db.Set<T>().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);
                List<PropertyInfo> 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.Entry<T>(model);
            Db.Set<T>().Attach(model);
            entry.State = EntityState.Modified;

        }

        /// <summary>
        /// 批量修改
        /// </summary>
        /// <param name="whereLambda"></param>
        /// <param name="updateExpression"></param>
        public void Update(Expression<Func<T, bool>> whereLambda, Expression<Func<T, T>> updateExpression)
        {
            Db.Set<T>().Where(whereLambda).Update(updateExpression);
        }

        /// <summary>
        /// 批量修改
        /// </summary>
        /// <param name="models"></param>
        /// <returns></returns>
        public void UpdateAll(List<T> 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, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames)
        {
            //查詢要修改的數據
            List<T> listModifing = Db.Set<T>().Where(whereLambda).ToList();
            Type t = typeof(T);
            List<PropertyInfo> proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            Dictionary<string, PropertyInfo> dictPros = new Dictionary<string, 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.Set<T>().Find(id);
        }

        /// <summary>
        /// 獲取預設一條數據,沒有則為NULL
        /// </summary>
        /// <param name="whereLambda"></param>
        /// <returns></returns>
        public T FirstOrDefault(Expression<Func<T, bool>> whereLambda = null)
        {
            if (whereLambda == null)
            {
                return Db.Set<T>().FirstOrDefault();
            }
            return Db.Set<T>().FirstOrDefault(whereLambda);
        }

        /// <summary>
        /// 獲取全部數據
        /// </summary>
        /// <returns></returns>
        public List<T> GetAll(string ordering = null)
        {
            return ordering == null
                ? Db.Set<T>().ToList()
                : Db.Set<T>().OrderBy(ordering).ToList();
        }

        /// <summary>
        /// 帶條件查詢獲取數據
        /// </summary>
        /// <param name="whereLambda"></param>
        /// <param name="ordering"></param>
        /// <returns></returns>
        public List<T> GetAll(Expression<Func<T, bool>> whereLambda, string ordering = null)
        {
            var iQueryable = Db.Set<T>().Where(whereLambda);
            return ordering == null
                ? iQueryable.ToList()
                : iQueryable.OrderBy(ordering).ToList();
        }

        /// <summary>
        /// 帶條件查詢獲取數據
        /// </summary>
        /// <param name="whereLambda"></param>
        /// <returns></returns>
        public IQueryable<T> GetAllIQueryable(Expression<Func<T, bool>> whereLambda = null)
        {
            return whereLambda == null ? Db.Set<T>() : Db.Set<T>().Where(whereLambda);
        }

        /// <summary>
        /// 獲取數量
        /// </summary>
        /// <param name="whereLambd"></param>
        /// <returns></returns>
        public int GetCount(Expression<Func<T, bool>> whereLambd = null)
        {
            return whereLambd == null ? Db.Set<T>().Count() : Db.Set<T>().Where(whereLambd).Count();
        }

        /// <summary>
        /// 判斷對象是否存在
        /// </summary>
        /// <param name="whereLambd"></param>
        /// <returns></returns>
        public bool Any(Expression<Func<T, bool>> whereLambd)
        {
            return Db.Set<T>().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 List<T> Page<TKey>(int pageIndex, int pageSize, out int rows, Expression<Func<T, TKey>> orderBy, Expression<Func<T, bool>> whereLambda = null, bool isOrder = true)
        {
            IQueryable<T> data = isOrder ?
                Db.Set<T>().OrderBy(orderBy) :
                Db.Set<T>().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 List<T> Page(int pageIndex, int pageSize, out int rows, string ordering, Expression<Func<T, bool>> whereLambda = null)
        {
            // 分頁 一定註意: Skip 之前一定要 OrderBy
            var data = Db.Set<T>().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 List<TDto> Select<TDto>(Expression<Func<T, bool>> whereLambda)
        {
            return Db.Set<T>().Where(whereLambda).Select<TDto>().ToList();
        }

        #endregion SELECT

        #region ORTHER

        /// <summary>
        /// 執行存儲過程或自定義sql語句--返回集合
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parms"></param>
        /// <param name="cmdType"></param>
        /// <returns></returns>
        public List<T> Query(string sql, List<SqlParameter> parms, CommandType cmdType = CommandType.Text)
        {
            return Query<T>(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 NullDatabaseInitializer<ReadDbContext>()); 改變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 Lazy<DbContext> _masterDb = new Lazy<DbContext>(() => new DbContextFactory().GetWriteDbContext());

        #endregion EF上下文對象(主庫)

        #region EF上下文對象(從庫)

        protected DbContext SlaveDb => IsReadWriteSeparation ? _slaveDb.Value : _masterDb.Value;
        private readonly Lazy<DbContext> _slaveDb = new Lazy<DbContext>(() => new DbContextFactory().GetReadDbContext());

        #endregion EF上下文對象(從庫)

        #region 自定義其他方法

        /// <summary>
        /// 執行存儲過程或自定義sql語句--返回集合(自定義返回類型)
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parms"></param>
        /// <param name="cmdType"></param>
        /// <returns></returns>
        public List<TModel> Query<TModel>(string sql, List<SqlParameter> 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.SqlQuery<TModel>(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, List<SqlParameter> 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 DbBase<T> : DbBase where T : class, new()
    {
        #region INSERT

        /// <summary>
        /// 新增 實體
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void Insert(T model)
        {
            MasterDb.Set<T>().Add(model);
        }

        /// <summary>
        /// 普通批量插入
        /// </summary>
        /// <param name="datas"></param>
        public void InsertRange(List<T> datas)
        {
            MasterDb.Set<T>().AddRange(datas);
        }

        #endregion INSERT

        #region DELETE

        /// <summary>
        /// 根據模型刪除
        /// </summary>
        /// <param name="model">包含要刪除id的對象</param>
        /// <returns></returns>
        public void Delete(T model)
        {
            MasterDb.Set<T>().Attach(model);
            MasterDb.Set<T>().Remove(model);
        }

        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="whereLambda"></param>
        public void Delete(Expression<Func<T, bool>> whereLambda)
        {
            MasterDb.Set<T>().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, List<string> proNames, bool isProUpdate = true)
        {
            //將 對象 添加到 EF中
            MasterDb.Set<T>().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);
                List<PropertyInfo> proInfos = t.GetPro

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、創建到目標板相關文件的鏈接 ln -s asm-arm asm ln -s arch-s3c24x0 asm-arm/arch ln -s proc-armv asm-arm/proc 2、創建include/config.mk文件,內容如下: ARM = arm CPU = arm920t B ...
  • 失敗原因: 1.telnet包未安裝,檢查telnet包是否安裝: 表示已安裝 2.telnet包已安裝,telnet-server未安裝,檢查telnet-server包是否安裝: 表示已安裝 3.telnet配置文件問題: 將disable對應的值修改為no或者註釋該行並重啟xinetd守護進程 ...
  • 一、BIOS更改 首先來bios更改:我們知道,uefi+gpt引導雖然出來的時間比較長,但是win7還不能完全的支持,所以在使用uefi+gpt安裝win7的時候就會出現各種錯誤!所以我們在安裝Windows 7的時候,不能把BIOS設置為“純UEFI”,並且必須禁用“Secure Boot”。下 ...
  • 一、Samba服務 Samba服務主要用於Linux伺服器給Windows用戶分享文件用 配置伺服器都需要以下5步操作 1.準備環境 1)關閉防火牆 systemctl stop firewalld 2)臨時關閉selinux sentenforce 0 或者在配置文件中永久關閉selinux vi ...
  • 分享一個由於KDE未被正確安裝導致ubuntu 無法用ssh正常訪問的問題解決過程 ...
  • 大家在學習正則表達式之前,首先要明確一點,並把它牢牢記在心裡,那就是: 在linux中,通配符是由shell解釋的,而正則表達式則是由命令解釋的,不要把二者搞混了。切記!!! 通常有三種文本處理工具/命令:grep、sed、awk,它們三者均可以解釋正則。下麵我就為大家介紹grep命令的使用方法。 ...
  • 一.介紹 二.服務端配置 1.關閉系統防火牆和selinux 查看系統防火牆的狀態,可以看到防火牆是開著的 [root@bogon ~] systemctl status firewalld ● firewalld.service firewalld dynamic firewall daemon ...
  • . NET Core 從2016年6月28日發佈,過去了將近一年的時間,但是在工作中發現大家對.net core的接受程度並不高,這隻是一個感覺,俗話說“沒有調查就沒有發言權”, 這兩天通過微信小程式在微信群里做了一個調查,參與的人數大概230人,從結果看大家都在等待.NET Core 2.0, 期 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...