基於C#的MongoDB資料庫開發應用(2)--MongoDB資料庫的C#開發

来源:http://www.cnblogs.com/wuhuacong/archive/2016/01/06/5106662.html
-Advertisement-
Play Games

在上篇博客《基於C#的MongoDB資料庫開發應用(1)--MongoDB資料庫的基礎知識和使用》裡面,我總結了MongoDB資料庫的一些基礎信息,併在最後面部分簡單介紹了資料庫C#驅動的開發 ,本文繼續這個主體,重點介紹MongoDB資料庫C#方面的使用和封裝處理過程,利用泛型和基類對象針對數據訪...


在上篇博客《基於C#的MongoDB資料庫開發應用(1)--MongoDB資料庫的基礎知識和使用》裡面,我總結了MongoDB資料庫的一些基礎信息,併在最後面部分簡單介紹了資料庫C#驅動的開發 ,本文繼續這個主題,重點介紹MongoDB資料庫C#方面的使用和封裝處理過程,利用泛型和基類對象針對數據訪問層進行的封裝處理。

前面介紹到,當前2.2版本的資料庫C#驅動的API,支持兩種不同的開發介面,一個是基於MongoDatabase的對象介面,一個是IMongoDatabase的對象介面,前者中規中矩,和我們使用Shell裡面的命令名稱差不多;後者IMongoDatabase的介面是基於非同步的,基本上和前者差別很大,而且介面都提供了非同步的處理操作。

本文主要介紹基於MongoDatabase的對象介面的封裝處理設置。

1、數據訪問層的設計

在結合MongoDB資料庫的C#驅動的特點,使用泛型和繼承關係,把常規的處理介面做了抽象性的封裝,以便封裝適合更多業務的介面,減少子類代碼及統一API的介面名稱。

首先我們來看看大概的設計思路,我們把實體類抽象一個實體基類,方便使用。

 

我們知道,在MongoDB資料庫的集合裡面,都要求文檔有一個_id欄位,這個是強制性的,而且這個欄位的存儲類型為ObjectId類型,這個值考慮了分散式的因素,綜合了機器碼,進程,時間戳等等方面的內容,它的構造如下所示。

ObjectId是一個12位元組的  BSON 類型字元串。按照位元組順序,依次代表:

  • 4位元組:UNIX時間戳
  • 3位元組:表示運行MongoDB的機器
  • 2位元組:表示生成此_id的進程
  • 3位元組:由一個隨機數開始的計數器生成的值

實體基類BaseEntity包含了一個屬性Id,這個是一個字元串型的對象(也可以使用ObjectId類型,但是為了方便,我們使用字元型,並聲明為ObjectId類型即可),由於我們聲明瞭該屬性對象為ObjectId類型,那麼我們就可以在C#代碼裡面使用字元串的ID類型了,代碼如下所示。

    /// <summary>
    /// MongoDB實體類的基類
    /// </summary>
    public class BaseEntity
    {        
        /// <summary>
        /// 基類對象的ID,MongoDB要求每個實體類必須有的主鍵
        /// </summary>
        [BsonRepresentation(BsonType.ObjectId)]        
        public string Id { get; set; }
    }

然後利用泛型的方式,把數據訪問層的介面提出來,並引入了數據訪問層的基類進行實現和重用介面,如下所示。

其中,上面幾個類的定義如下所示。

數據訪問層基類BaseDAL的類定義如下所示,主要就是針對上面的IBaseDAL<T>介面進行實現。

有了這些基類的實現,我們對於實體類的處理就非常方便、統一了,基本上不需要在複製大量的代碼來實現基礎的增刪改查分頁實現了。

例如上面的User集合(表對象)的數據訪問類定義如下所示,在對象的定義的時候,指定對應的實體類,併在構造函數裡面指定對應的集合名稱就可以實例化一個數據訪問類了。

    /// <summary>
    /// 數據表User對應的具體數據訪問類
    /// </summary>
    public class User : BaseDAL<UserInfo>, IBaseDAL<UserInfo>
    {
        /// <summary>
        /// 預設構造函數
        /// </summary>
        public User() 
        {
            this.entitysName = "users";//對象在資料庫的集合名稱
        }

        .................

2、基類各種介面的實現

前面小節我們介紹了實體基類,數據訪問層基類介面和基類實現,以及具體集合對象的實現類的定義關係,通過泛型和繼承關係,我們很好的抽象了各種對象的增刪改查、分頁等操作,子類繼承了BaseDAL基類後,就自然而然的具有了非常強大的介面處理功能了。下麵我們來繼續詳細介紹基於C#驅動的MongoDB資料庫是如何進行各種增刪改查等封裝的。

1)構造MongoDatabase對象

首先我們需要利用連接字元串來構建MongoDatabase對象,因為所有的介面都是基於這個對象進行處理的,代碼如下所示。

        /// <summary>
        /// 根據資料庫配置信息創建MongoDatabase對象,如果不指定配置信息,則從預設信息創建
        /// </summary>
        /// <param name="databaseName">資料庫名稱,預設空為local</param>
        /// <returns></returns>
        protected virtual MongoDatabase CreateDatabase()
        {
            string connectionString = null;

            if (!string.IsNullOrEmpty(dbConfigName))
            {
                //從配置文件中獲取對應的連接信息
                connectionString = ConfigurationManager.ConnectionStrings[dbConfigName].ConnectionString;                
            }
            else
            {
                connectionString = defaultConnectionString;
            }

            var client = new MongoClient(connectionString);
            var database = client.GetServer().GetDatabase(new MongoUrl(connectionString).DatabaseName);

            return database;
        }

2)構建MongoCollection對象

上面構建了MongoDatabase對象後,我們需要基於這個基礎上再創建一個對象的MongoCollection對象,這個就是類似我們關係資料庫裡面的表對象的原型了。

        /// <summary>
        /// 獲取操作對象的MongoCollection集合,強類型對象集合
        /// </summary>
        /// <returns></returns>
        protected virtual MongoCollection<T> GetCollection()
        {
            MongoDatabase database = CreateDatabase();
            return database.GetCollection<T>(this.entitysName);
        }

3)查詢單個對象

利用MongoCollection對象,我們可以通過API介面獲取對應的對象,單個對象的介面為FindOneById(也可以用FindOne介面,如註釋部分的代碼),我們具體的處理代碼如下所示

        /// <summary>
        /// 查詢資料庫,檢查是否存在指定ID的對象
        /// </summary>
        /// <param name="key">對象的ID值</param>
        /// <returns>存在則返回指定的對象,否則返回Null</returns>
        public virtual T FindByID(string id)
        {
            ArgumentValidation.CheckForEmptyString(id, "傳入的對象id為空");

            MongoCollection<T> collection = GetCollection();
            return collection.FindOneById(new ObjectId(id)); //FindOne(Query.EQ("_id", new ObjectId(id)));
        }

如果基於條件的單個記錄查詢,我們可以使用Expression<Func<T, bool>>和IMongoQuery的參數進行處理,如下代碼所示。

        /// <summary>
        /// 根據條件查詢資料庫,如果存在返回第一個對象
        /// </summary>
        /// <param name="match">條件表達式</param>
        /// <returns>存在則返回指定的第一個對象,否則返回預設值</returns>
        public virtual T FindSingle(Expression<Func<T, bool>> match)
        {
            MongoCollection<T> collection = GetCollection();
            return collection.AsQueryable().Where(match).FirstOrDefault();
        }

        /// <summary>
        /// 根據條件查詢資料庫,如果存在返回第一個對象
        /// </summary>
        /// <param name="query">條件表達式</param>
        /// <returns>存在則返回指定的第一個對象,否則返回預設值</returns>
        public virtual T FindSingle(IMongoQuery query)
        {
            MongoCollection<T> collection = GetCollection();
            return collection.FindOne(query);
        } 

4)IQueryable的介面利用

使用過EF的實體框架的話,我們對其中的IQueryable<T>印象很深刻,它可以給我提供很好的LINQ語法獲取對應的信息,它可以通過使用Expression<Func<T, bool>>和IMongoQuery的參數來進行條件的查詢操作,MongoCollection對象有一個AsQueryable()的API進行轉換,如下所示。

        /// <summary>
        /// 返回可查詢的記錄源
        /// </summary>
        /// <returns></returns>
        public virtual IQueryable<T> GetQueryable()
        {
            MongoCollection<T> collection = GetCollection();
            IQueryable<T> query = collection.AsQueryable();

            return query.OrderBy(this.SortPropertyName, this.IsDescending);
        }

如果是通過使用Expression<Func<T, bool>>和IMongoQuery的參數,那麼處理的介面代碼如下所示。

        /// <summary>
        /// 根據條件表達式返回可查詢的記錄源
        /// </summary>
        /// <param name="match">查詢條件</param>
        /// <param name="sortPropertyName">排序表達式</param>
        /// <param name="isDescending">如果為true則為降序,否則為升序</param>
        /// <returns></returns>
        public virtual IQueryable<T> GetQueryable(Expression<Func<T, bool>> match, string sortPropertyName, bool isDescending = true)
        {
            MongoCollection<T> collection = GetCollection();
            IQueryable<T> query = collection.AsQueryable();
            if (match != null)
            {
                query = query.Where(match);
            }
            return query.OrderBy(sortPropertyName, isDescending);
        }
        /// <summary>
        /// 根據條件表達式返回可查詢的記錄源
        /// </summary>
        /// <param name="query">查詢條件</param>
        /// <param name="sortPropertyName">排序表達式</param>
        /// <param name="isDescending">如果為true則為降序,否則為升序</param>
        /// <returns></returns>
        public virtual IQueryable<T> GetQueryable(IMongoQuery query, string sortPropertyName, bool isDescending = true)
        {
            MongoCollection<T> collection = GetCollection();
            IQueryable<T> queryable = collection.Find(query).AsQueryable();

            return queryable.OrderBy(sortPropertyName, isDescending);
        }

5)集合的查詢處理

通過利用上面的IQueryable<T>對象,以及使用Expression<Func<T, bool>>和IMongoQuery的參數,我們很好的進行集合的查詢處理操作的了,具體代碼如下所示

        /// <summary>
        /// 根據條件查詢資料庫,並返回對象集合
        /// </summary>
        /// <param name="match">條件表達式</param>
        /// <returns>指定對象的集合</returns>
        public virtual IList<T> Find(Expression<Func<T, bool>> match)
        {
            return GetQueryable(match).ToList();
        }

        /// <summary>
        /// 根據條件查詢資料庫,並返回對象集合
        /// </summary>
        /// <param name="query">條件表達式</param>
        /// <returns>指定對象的集合</returns>
        public virtual IList<T> Find(IMongoQuery query)
        {
            MongoCollection<T> collection = GetCollection();
            return collection.Find(query).ToList();
        }

對於分頁,我們是非常需要的,首先在大數據的集合裡面,我們不可能一股腦的把所有的數據全部返回,因此根據分頁參數返回有限數量的集合處理就是我們應該做的,分頁的操作代碼和上面很類似,只是利用了Skip和Take的介面,返回我們需要的記錄數量就可以了。

        /// <summary>
        /// 根據條件查詢資料庫,並返回對象集合(用於分頁數據顯示)
        /// </summary>
        /// <param name="match">條件表達式</param>
        /// <param name="info">分頁實體</param>
        /// <returns>指定對象的集合</returns>
        public virtual IList<T> FindWithPager(Expression<Func<T, bool>> match, PagerInfo info)
        {
            int pageindex = (info.CurrenetPageIndex < 1) ? 1 : info.CurrenetPageIndex;
            int pageSize = (info.PageSize <= 0) ? 20 : info.PageSize;

            int excludedRows = (pageindex - 1) * pageSize;

            IQueryable<T> query = GetQueryable(match);
            info.RecordCount = query.Count();

            return query.Skip(excludedRows).Take(pageSize).ToList();
        }

或者是下麵的代碼

        /// <summary>
        /// 根據條件查詢資料庫,並返回對象集合(用於分頁數據顯示)
        /// </summary>
        /// <param name="query">條件表達式</param>
        /// <param name="info">分頁實體</param>
        /// <returns>指定對象的集合</returns>
        public virtual IList<T> FindWithPager(IMongoQuery query, PagerInfo info)
        {
            int pageindex = (info.CurrenetPageIndex < 1) ? 1 : info.CurrenetPageIndex;
            int pageSize = (info.PageSize <= 0) ? 20 : info.PageSize;

            int excludedRows = (pageindex - 1) * pageSize;

            IQueryable<T> queryable = GetQueryable(query);
            info.RecordCount = queryable.Count();

            return queryable.Skip(excludedRows).Take(pageSize).ToList();
        }

6)對象的寫入操作

對象的寫入可以使用save,它是根據_id的來決定插入還是更新的,如下代碼所示。

        /// <summary>
        /// 保存指定對象到資料庫中,根據Id的值,決定是插入還是更新
        /// </summary>
        /// <param name="t">指定的對象</param>
        /// <returns>執行成功指定對象信息</returns>
        public virtual T Save(T t)
        {
            ArgumentValidation.CheckForNullReference(t, "傳入的對象t為空");

            MongoCollection<T> collection = GetCollection();
            var result = collection.Save(t);
            return t;
        }

插入記錄就可以利用insert方法進行處理的,代碼如下所示。

        /// <summary>
        /// 插入指定對象到資料庫中
        /// </summary>
        /// <param name="t">指定的對象</param>
        /// <returns>執行成功返回<c>true</c>,否則為<c>false</c></returns>
        public virtual bool Insert(T t)
        {
            ArgumentValidation.CheckForNullReference(t, "傳入的對象t為空");

            MongoCollection<T> collection = GetCollection();
            var result = collection.Insert(t);
            return result != null && result.DocumentsAffected > 0;
        }

如果是批量插入,可以利用它的insertBatch的方法進行處理,具體代碼如下所示。

        /// <summary>
        /// 插入指定對象集合到資料庫中
        /// </summary>
        /// <param name="list">指定的對象集合</param>
        /// <returns>執行成功返回<c>true</c>,否則為<c>false</c></returns>
        public virtual bool InsertBatch(IEnumerable<T> list)
        {
            ArgumentValidation.CheckForNullReference(list, "傳入的對象list為空");

            MongoCollection<T> collection = GetCollection();
            var result = collection.InsertBatch(list);
            return result.Any(s => s != null && s.DocumentsAffected > 0); //部分成功也返回true
        }

7)對象的更新操作

更新操作分為了兩個不同的部分,一個是全部的記錄更新,也就是整個JSON的替換操作了,一般我們是在原來的基礎上進行更新的,如下代碼所示。

        /// <summary>
        /// 更新對象屬性到資料庫中
        /// </summary>
        /// <param name="t">指定的對象</param>
        /// <param name="id">主鍵的值</param>
        /// <returns>執行成功返回<c>true</c>,否則為<c>false</c></returns>
        public virtual bool Update(T t, string id)
        {
            ArgumentValidation.CheckForNullReference(t, "傳入的對象t為空");
            ArgumentValidation.CheckForEmptyString(id, "傳入的對象id為空");

            bool result = false;
            MongoCollection<T> collection = GetCollection();
            var existing = FindByID(id);
            if (existing != null)
            {
                var resultTmp = collection.Save(t);
                result = resultTmp != null && resultTmp.DocumentsAffected > 0;
            }

            return result;
        }

還有一種方式是部分更新,也就是更新裡面的指定一個或幾個欄位,不會影響其他欄位,也就不會全部替換掉其他內容的操作了。這裡利用了一個UpdateBuilder<T>的對象,用來指定那些欄位需要更新,以及這些欄位的值內容的,具體的更新代碼如下所示。

        /// <summary>
        /// 封裝處理更新的操作
        /// </summary>
        /// <param name="id">主鍵的值</param>
        /// <param name="update">更新對象</param>
        /// <returns>執行成功返回<c>true</c>,否則為<c>false</c></returns>
        public virtual bool Update(string id, UpdateBuilder<T> update)
        {
            ArgumentValidation.CheckForNullReference(update, "傳入的對象update為空");
            ArgumentValidation.CheckForEmptyString(id, "傳入的對象id為空");

            var query = Query.EQ("_id", new ObjectId(id));
            MongoCollection<T> collection = GetCollection();
            var result = collection.Update(query, update);
            return result != null && result.DocumentsAffected > 0;
        }

部分更新,可以結合使用Inc和Set方法來進行處理,如下是我在子類裡面利用到上面的Update部分更新的API進行處理個別欄位的更新操作。

        /// <summary>
        /// 為用戶增加歲數
        /// </summary>
        /// <param name="id">記錄ID</param>
        /// <param name="addAge">待增加的歲數</param>
        /// <returns></returns>
        public bool IncreaseAge(string id, int addAge)
        {
            //增加指定的歲數
            var query = Query<UserInfo>.EQ(s => s.Id, id);
            var update = Update<UserInfo>.Inc(s => s.Age, addAge);

            var collection = GetCollection();
            var result = collection.Update(query, update);
            return result != null && result.DocumentsAffected > 0;
        }

        /// <summary>
        /// 單獨修改用戶的名稱
        /// </summary>
        /// <param name="id">記錄ID</param>
        /// <param name="newName">用戶新名稱</param>
        /// <returns></returns>
        public bool UpdateName(string id, string newName)
        {
            //增加指定的歲數
            var query = Query<UserInfo>.EQ(s => s.Id, id);
            var update = Update<UserInfo>.Set(s => s.Name, newName);

            var collection = GetCollection();
            var result = collection.Update(query, update);
            return result != null && result.DocumentsAffected > 0;
        }

8)對象的刪除操作

對象的刪除,一般可以利用條件進行刪除,如單個刪除可以使用_id屬性進行處理,也可以利用批量刪除的介面進行刪除操作,代碼如下所示。

        /// <summary>
        /// 根據指定對象的ID,從資料庫中刪除指定對象
        /// </summary>
        /// <param name="id">對象的ID</param>
        /// <returns>執行成功返回<c>true</c>,否則為<c>false</c></returns>
        public virtual bool Delete(string id)
        {
            ArgumentValidation.CheckForEmptyString(id, "傳入的對象id為空");

            MongoCollection<T> collection = GetCollection();
            //var result = collection.Remove(Query<T>.EQ(s => s.Id, id));
            var result = collection.Remove(Query.EQ("_id", new ObjectId(id)));
            return result != null && result.DocumentsAffected > 0;
        }

其中上面註釋的var result = collection.Remove(Query<T>.EQ(s => s.Id, id));代碼,就是利用了強類型的對象屬性和值進行移除,一樣可以的。

對於批量刪除,可以利用Query的不同進行處理。

        /// <summary>
        /// 根據指定對象的ID,從資料庫中刪除指定指定的對象
        /// </summary>
        /// <param name="idList">對象的ID集合</param>
        /// <returns>執行成功返回<c>true</c>,否則為<c>false</c></returns>
        public virtual bool DeleteBatch(List<string> idList)
        {
            ArgumentValidation.CheckForNullReference(idList, "傳入的對象idList為空");

            MongoCollection<T> collection = GetCollection();
            var query = Query.In("_id", new BsonArray(idList));
            var result = collection.Remove(query);
            return result != null && result.DocumentsAffected > 0;
        }

或者基於IMongoQuery的條件進行處理。

        /// <summary>
        /// 根據指定條件,從資料庫中刪除指定對象
        /// </summary>
        /// <param name="match">條件表達式</param>
        /// <returns>執行成功返回<c>true</c>,否則為<c>false</c></returns>
        public virtual bool DeleteByQuery(IMongoQuery query)
        {
            MongoCollection<T> collection = GetCollection();
            var result = collection.Remove(query);
            return result != null && result.DocumentsAffected > 0;
        } 

9)其他相關介面

一般除了上面的介面,還有一些其他的介面,如獲取記錄的總數、判斷條件的記錄是否存在等也是很常見的,他們的代碼封裝如下所示。

        /// <summary>
        /// 獲取表的所有記錄數量
        /// </summary>
        /// <returns></returns>
        public virtual int GetRecordCount()
        {
            return GetQueryable().Count();
        }
        /// <summary>
        /// 根據查詢條件,判斷是否存在記錄
        /// </summary>
        /// <param name="match">條件表達式</param>
        /// <returns></returns>
        public virtual bool IsExistRecord(Expression<Func<T, bool>> match)
        {
            return GetQueryable(match).Any();//.Count() > 0
        }

        /// <summary>
        /// 根據查詢條件,判斷是否存在記錄
        /// </summary>
        /// <param name="query">條件表達式</param>
        /// <returns></returns>
        public virtual bool IsExistRecord(IMongoQuery query)
        {
            return GetQueryable(query).Any();//.Count() > 0
        }

 

非常感謝您的詳細閱讀,以上基本上就是我對整個MongoDB資料庫的各個介面的基類封裝處理了,其中已經覆蓋到了基礎的增刪改查、分頁等操作介面,以及一些特殊的條件處理介面的擴展,我們利用這些封裝好的基類很好的簡化了子類的代碼,而且可以更方便的在基類的基礎上進行特殊功能的擴展處理。

當然,以上介紹的都不是最新的介面,是2.0(或2.2)版本之前的介面實現,雖然在2.2裡面也還可以利用上面的MongoDatabase對象介面,但是IMongoDatabase最新的介面已經全面相容非同步的操作,但也是一個很大的跳躍,基本上引入了不同的介面命名和處理方式,利用非同步可以支持更好的處理體驗,但是也基本上是需要對所有的介面進行了全部的重寫了。

下一篇我會專門介紹一下基於最新的非同步介面如何實現這些常規增刪改查、分頁等的基類實現封裝處理。

 


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

-Advertisement-
Play Games
更多相關文章
  • #import int main(int argc, const char * argv[]) { @autoreleasepool { /** * length獲取字元串長度,即獲取字元個數 */// NSString *str=...
  • Java 7支持整個目錄樹的遍歷;Demo:import java.io.IOException;import java.nio.file.FileVisitResult;import java.nio.file.Files;import java.nio.file.Path;import java...
  • Java中PrintStream(列印輸出流)PrintStream 是列印輸出流,它繼承於FilterOutputStream。PrintStream 是用來裝飾其它輸出流。它能為其他輸出流添加了功能,使它們能夠方便地列印各種數據值表示形式。與其他輸出流不同,PrintStream 永遠不會拋出 ...
  • 最近做個發郵件的功能,需要將日誌文件通過郵件發送回來用於分析,但是日誌文件可能會超級大,測算下來一天可能會有800M的大小。所以壓縮是不可避免了,delphi中的預設壓縮演算法整了半天不太好使,就看了看7z,在windows下有dll那麼就用它吧。下載7z.dll,還有一個delphi的開發sdk文件...
  • 最近研究ehcache同步時發現一個問題:現有A、B兩個伺服器,由A伺服器向B伺服器同步信息,採用RMI方式手動方式進行同步配置信息如下: 同步的核心代碼:String key = StringUtils.leftPa...
  • 1、ArrayList非線程安全基於對象數組get(int index)不需要遍曆數組,速度快;iterator()方法中調用了get(int index),所以速度也快set(int index, E e)不需要遍曆數組,速度快add方法需要考慮擴容與數組複製問題,速度慢remove(Object...
  • 語言的數學運算和一些簡單的函數整理如下:向量可以進行那些常規的算術運算,不同長度的向量可以相加,這種情況下最短的向量將被迴圈使用。> x a x * a[1] 10 20 30 40> x + a[1] 11 12 13 14> sum(x) #對x中的元素求和[1] 10> prod(x) #.....
  • MyEclipse 快捷鍵1(CTRL)-------------------------------------Ctrl+1 快速修複Ctrl+D: 刪除當前行Ctrl+Q定位到最後編輯的地方Ctrl+L定位在某行Ctrl+O快速顯示 OutLineCtrl+T快速顯示當前類的繼承結構Ctrl+W...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...