基於SqlSugar的開發框架循序漸進介紹(27)-- 基於MongoDB的資料庫操作整合

来源:https://www.cnblogs.com/wuhuacong/archive/2023/04/13/17314207.html
-Advertisement-
Play Games

SqlSugar的開發框架本身主要是基於常規關係型資料庫設計的框架,支持多種資料庫類型的接入,如SqlServer、MySQL、Oracle、PostgreSQL、SQLite等資料庫,非關係型資料庫的MongoDB資料庫也可以作為擴展整合到開發框架裡面,通過基類的繼承關係很好的封裝了相關的基礎操作... ...


SqlSugar的開發框架本身主要是基於常規關係型資料庫設計的框架,支持多種資料庫類型的接入,如SqlServer、MySQL、Oracle、PostgreSQL、SQLite等資料庫,非關係型資料庫的MongoDB資料庫也可以作為擴展整合到開發框架裡面,通過基類的繼承關係很好的封裝了相關的基礎操作功能,極大的減少相關處理MongoDB的代碼,並提供很好的開發效率。本篇隨筆介紹如何在SqlSugar的開發框架整合MongoDB資料庫的開發。

1、MongDB的簡單介紹

MongoDB是一款由C++編寫的高性能、開源、無模式的常用非關係型資料庫產品,是非關係資料庫當中功能最豐富、最像關係資料庫的資料庫。它擴展了關係型資料庫的眾多功能,例如:輔助索引、範圍查詢、排序等。 

MongoDB 是一個介於關係資料庫和非關係資料庫之間的產品,是非關係資料庫當中功能最豐富,最像關係資料庫的。它支持的數據結構非常鬆散,是類似Json的Bson格式,因此可以存儲比較複雜的數據類型。
MongoDB 最大的特點是它支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係資料庫單表查詢的絕大部分功能,而且還支持對數據建立索引。並且MongoDB-4.2版本開始已經支持分散式事務功能。

MongoDB資料庫有幾個簡單的概念需要瞭解一下。

    1)MongoDB中的 database 有著和我們熟知的"資料庫"一樣的概念 (對 Oracle 來說就是 schema)。一個 MongoDB 實例中,可以有零個或多個資料庫,每個都作為一個高等容器,用於存儲數據。

    2)資料庫中可以有零個或多個 collections (集合)。集合和傳統意義上的 table 基本一致,可以簡單的把兩者看成是一樣的東西。

    3)集合是由零個或多個 documents (文檔)組成。同樣,一個文檔可以看成是一 row

    4)文檔是由零個或多個 fields (欄位)組成。,對應的就是關係資料庫的 columns

    5)Indexes (索引)在 MongoDB 中扮演著和它們在 RDBMS 中一樣的角色,都是為了提高查詢的效率。

    6)Cursors (游標)和上面的五個概念都不一樣,但是它非常重要,並且經常被忽視,其中最重要的你要理解的一點是,游標是當你問 MongoDB 拿數據的時候,它會給你返回一個結果集的指針而不是真正的數據,這個指針我們叫它游標,我們可以拿游標做我們想做的任何事情,比如說計數或者跨行之類的,而無需把真正的數據拖下來,在真正的數據上操作。

 它們的對比關係圖如下所示。

數據在Mongodb裡面都是以Json格式方式進行存儲的,如下所示是其中的一個記錄內容。

BSON格式

Bson是一種類Json的一種二進位形式的存儲格式,簡稱Binary Json,它和Json一樣,支持內嵌的文檔對象和數組對象,但是Bson有Json沒有的一些數據類型,如Date和BinData類型。

Bson可以做為網路數據交換的一種存儲形式,這個有點類似於Google的Protocol Buffer,但是Bson是一種schema-less的存儲形式,它的優點是靈活性高,但它的缺點是空間利用率不是很理想,Bson有三個特點:輕量性、可遍歷性、高效性,

{“hello":"world"} 這是一個Bson的例子,其中"hello"是key name,它一般是cstring類型,位元組表示是cstring::= (byte*) "/x00" ,其中*表示零個或多個byte位元組,/x00表示結束符;後面的"world"是value值,它的類型一般是string,double,array,binarydata等類型。

MongDB資料庫本身支持多種開發語言的驅動,MongoDB有官方的驅動如下:

我們框架基於C#開發,使用的時候,安裝MongoDB的C#的驅動 MongoDB.Driver 即可。

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

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

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

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

 

2、基於MongoDB資料庫的封裝處理

以前介紹過,針對常規關係型資料庫的開發,在SqlSugar開發框架上,我們設計一些基類,以便重用相關的邏輯代碼,通過泛型的約束,可以提供強類型的數據介面,非常方便。

其中MyCrudService裡面封裝了很多CRUD以及常用的處理方法。類似的處理方式,我們專門為MongoDB資料庫的訪問操作,設計了一個功能強大的基類即可。

在資料庫表的實體對應關係上,我們依舊遵循則相應的設計規則,基類實體採用IEntity<string>的介面類型,因此他們具有一個字元串的Id類型。其他業務對象繼承該基類對象即可。

    /// <summary>
    /// 基於MongoDB的實體類基類
    /// </summary>
    public class BaseMongoEntity : Entity<string>
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public override string Id { get; set; }
    }

相應的,我們根據常規資料庫的基類介面名稱,在處理MongoDB資料庫的操作介面的時候,名稱保持一致性。

其中TEntity為強類型實體類型,而TGetListInput 是定義的一個分頁介面。定義的基類介面代碼如下所示。

其中介面對象 CurrentApiUser是我們用戶上下文的信息,包含一些駐留在ClainPrincipal中的信息,用於記錄訪問介面的用戶信息的。

其他介面定義類似的處理即可。

基類介面的實現類,就是我們需要設計的MongoDB資料庫操作類了,初始化類的代碼如下所示。

    /// <summary>
    /// MongoDB基礎倉儲實現
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public abstract class BaseMongoService<TEntity, TGetListInput> : IBaseMongoService<TEntity, TGetListInput> 
        where TEntity : class, IEntity<string>, new()
        where TGetListInput : IPagedAndSortedResultRequest
    {
        protected readonly IMongoDBContext mongoContext = NullMongoDBContext.Instance;//空實現
        protected IMongoCollection<TEntity> collection;           //強類型對象集合
        protected IMongoCollection<BsonDocument> bsonCollection; //弱類型集合BsonDocument集合
        /// <summary>
        /// 當前Api用戶信息
        /// </summary>
        public IApiUserSession CurrentApiUser { get; set; } = NullApiUserSession.Instance;//空實現

        /// <summary>
        /// 構造函數
        /// </summary>
        protected BaseMongoService()
        {
            //如果SerivcePovider已經設置值,則獲得註入的介面對象
            if (ServiceLocator.SerivcePovider != null)
            {
                CurrentApiUser = ServiceLocator.GetService<IApiUserSession>();
                mongoContext = ServiceLocator.GetService<IMongoDBContext>();
                collection = mongoContext.GetCollection<TEntity>(typeof(TEntity).Name);//強類型對象集合
                bsonCollection = mongoContext.GetCollection<BsonDocument>(typeof(TEntity).Name);//弱類型集合BsonDocument集合
            }
        }
        /// <summary>
        /// 獲取所有記錄
        /// </summary>
        /// <returns></returns>
        public virtual async Task<ListResultDto<TEntity>> GetAllAsync()
        {
            var all = await collection.FindAsync(Builders<TEntity>.Filter.Empty);
            var list = await all.ToListAsync();
            return new ListResultDto<TEntity>()
            {
                Items = list
            };
        }

我們通過構建對應的強類型Collection和弱類型Collection,來操作實體類和BsonDocument的相關操作的。其中的上下文對象,參考隨筆《NoSQL – MongoDB Repository Implementation in .NET Core with Unit Testing example》進行的處理。

   /// <summary>
    /// MongoDB 上下文對象
    /// </summary>
    public class MongoDBContext : IMongoDBContext
    {
        private IMongoDatabase _db { get; set; }
        private MongoClient _mongoClient { get; set; }
        public IClientSessionHandle Session { get; set; }

        public MongoDBContext(IOptions<Mongosettings> configuration)
        {
            _mongoClient = new MongoClient(configuration.Value.Connection);
            _db = _mongoClient.GetDatabase(configuration.Value.DatabaseName);
        }

        /// <summary>
        /// 獲取強類型集合對象
        /// </summary>
        /// <typeparam name="T">對象類型</typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        public IMongoCollection<T> GetCollection<T>(string name) where T : class, new()
        {
            return _db.GetCollection<T>(name);
        }
    }

    public interface IMongoDBContext
    {
        IMongoCollection<T> GetCollection<T>(string name) where T : class, new();
    }

通過IOptions 方式我們註入對應的MongoDB資料庫配置信息,在appsettings.json中添加根節點內容。

  "MongoSettings": {
    "Connection": "mongodb://localhost:27017/", //MongoDB連接字元串
    "DatabaseName": "iqidi" //MongoDB資料庫名稱
  },

我們在啟動Web API的時候,在Program.cs 代碼中配置好就可以了。

//MongoDB配置
builder.Services.Configure<Mongosettings>(builder.Configuration.GetSection("MongoSettings"));

預設初始化的IMongoDBContext是一個空介面,我們可以在Web API啟動的時候,指定一個具體的實現就可以了

//添加IMongoContext實現類
builder.Services.AddSingleton<IMongoDBContext, MongoDBContext>();

對於基類介面,分頁查詢獲取對應列表數據,是常規的處理方式,預設需要排序、分頁,返回對應的數據結構,如下代碼所示。

        /// <summary>
        /// 根據條件獲取列表
        /// </summary>
        /// <param name="input">分頁查詢條件</param>
        /// <returns></returns>
        public virtual async Task<PagedResultDto<TEntity>> GetListAsync(TGetListInput input)
        {
            var query = CreateFilteredQueryAsync(input);
            var totalCount = await query.CountAsync();
            
            //排序處理
            query = ApplySorting(query, input);
            //分頁處理
            query = ApplyPaging(query, input);
            //獲取列表
            var list = await query.ToListAsync();

            return new PagedResultDto<TEntity>(
               totalCount,
               list
           );
        }

其中PagedResultDto 是我們SqlSugar開發框架參照ABP框架定義一個數據結構,包含一個TotalCount數量和一個Items的對象集合。而其中 CreateFilteredQueryAsync 是定義的一個可供業務子類重寫的函數,用來處理具體的查詢條件。在基類BaseMongoService中只是提供一個預設的可查詢對象。

        /// <summary>
        /// 留給子類實現過濾條件的處理
        /// </summary>
        /// <returns></returns>
        protected virtual IMongoQueryable<TEntity> CreateFilteredQueryAsync(TGetListInput input)
        {
            return collection.AsQueryable();
        }

例如,對於一個具體的業務對象操作類,CustomerService的定義如下所示,並且具體化查詢的條件處理,如下代碼所示。

namespace SugarProject.Core.MongoDB
{
    /// <summary>
    /// 基於MongoDB資料庫的應用層服務介面實現
    /// </summary>
    public class CustomerService : BaseMongoService<CustomerInfo, CustomerPagedDto>, ICustomerService
    {
        /// <summary>
        /// 構造函數
        /// </summary>
        public CustomerService()
        {
        }
        /// <summary>
        /// 自定義條件處理
        /// </summary>
        /// <param name="input">查詢條件Dto</param>
        /// <returns></returns>
        protected override IMongoQueryable<CustomerInfo> CreateFilteredQueryAsync(CustomerPagedDto input)
        {
            var query = base.CreateFilteredQueryAsync(input);

            query = query
                .Where(t=> !input.ExcludeId.IsNullOrWhiteSpace() && t.Id != input.ExcludeId) //不包含排除ID
                .Where(t=> !input.Name.IsNullOrWhiteSpace() && t.Name.Contains(input.Name)) //如需要精確匹配則用Equals                                                                                             //年齡區間查詢
                .Where(t=> input.AgeStart.HasValue && t.Age >= input.AgeStart.Value)
                .Where(t => input.AgeEnd.HasValue && t.Age <= input.AgeEnd.Value)
                //創建日期區間查詢
                .Where(t => input.CreateTimeStart.HasValue && t.CreateTime >= input.CreateTimeStart.Value)
                .Where(t => input.CreateTimeEnd.HasValue && t.CreateTime <= input.CreateTimeEnd.Value)
                ;

            return query;
        }

這個處理方式類似於常規關係型資料庫的處理方式,就是對條件的判斷處理。而具體的業務對象模型,和常規框架的實體類很類似。

    /// <summary>
    /// 客戶信息
    /// 繼承自BaseMongoEntity,擁有Id主鍵屬性
    /// </summary>
    public class CustomerInfo : BaseMongoEntity
    {
        /// <summary>
        /// 預設構造函數(需要初始化屬性的在此處理)
        /// </summary>
        public CustomerInfo()
        {
            this.CreateTime = System.DateTime.Now;
        }

        #region Property Members

        /// <summary>
        /// 姓名
        /// </summary>
        public virtual string Name { get; set; }
        /// <summary>
        /// 年齡
        /// </summary>
        public virtual int Age { get; set; }
        /// <summary>
        /// 創建人
        /// </summary>
        public virtual string Creator { get; set; }
        /// <summary>
        /// 創建時間
        /// </summary>
        public virtual DateTime CreateTime { get; set; }

        #endregion
    }

對於插入和更新操作等常規操作,我們調用普通的Collection操作處理就可以了

        /// <summary>
        /// 創建對象
        /// </summary>
        /// <param name="input">實體對象</param>
        /// <returns></returns>
        public virtual async Task InsertAsync(TEntity input)
        {
            SetObjectIdIfEmpty(input);//如果Id為空,設置為ObjectId的值
            await collection.InsertOneAsync(input);
        }

        /// <summary>
        /// 更新記錄
        /// </summary>
        public virtual async Task<bool> UpdateAsync(TEntity input)
        {
            SetObjectIdIfEmpty(input);//如果Id為空,設置為ObjectId的值

            //await _dbSet.ReplaceOneAsync(Builders<TEntity>.Filter.Eq("_id", input.Id), input);

            //要修改的欄位
            var list = new List<UpdateDefinition<TEntity>>();
            foreach (var item in input.GetType().GetProperties())
            {
                if (item.Name.ToLower() == "id") continue;
                list.Add(Builders<TEntity>.Update.Set(item.Name, item.GetValue(input)));
            }
            var updatefilter = Builders<TEntity>.Update.Combine(list);
            var update = await collection.UpdateOneAsync(Builders<TEntity>.Filter.Eq("_id", input.Id), updatefilter);
            var result = update != null && update.ModifiedCount > 0;
            return result;
        }

更新操作,有一種整個替換更新,還有一個是部分更新,它們兩者是有區別的。如果對於部分欄位的更新,那麼操作如下所示 ,主要是利用UpdateDefinition對象來指定需要更新那些欄位屬性及值等信息。

        /// <summary>
        /// 封裝處理更新的操作(部分欄位更新)
        /// </summary>
        /// <example>
        ///  var update = Builders<UserInfo>.Update.Set(s => s.Name, newName);
        /// </example>
        public virtual async Task<bool> UpdateAsync(string id, UpdateDefinition<TEntity> update)
        {
            var result = await collection.UpdateOneAsync(s => s.Id == id, update, new UpdateOptions() { IsUpsert = true });
            return result != null && result.ModifiedCount > 0;
        }

根據MongoDB資料庫的特性,我們儘量細化對資料庫操作的基類介面,定義所需的介面函數即可。

對於Web API的控制器設計,我們在之前的隨筆也有介紹,為常規授權處理的BaseApiController,為常規業務CRUD等介面處理的BusinessController,如下所示。

 

其中ControllerBase是.net core Web API中的標準控制器基類,我們由此派生一個LoginController用於登錄授權,而BaseApiController則處理常規介面用戶身份信息,而BusinessController則是對標準的增刪改查等基礎介面進行的封裝,我們實際開發的時候,只需要開發編寫類似CustomerController基類即可。

而對於 MongoDB的Web API控制器,我們為了方便開發,也設計了同類型的Web API 控制器基類。

 其中MongoBaseController基類具有常規的CRUD的介面定義處理,只要繼承它就可以了,而如果只是繼承BaseApiController這需要自定義控制器介面的方法。

最後我們啟動Swagger進行測試對應的介面即可,實際還可以整合在UI中進行測試處理。我們安裝MongoDB資料庫的管理工具後,可以在MongoDBCompass 中進行查詢對應資料庫的數據。

    /// <summary>
    /// 客戶信息的控制器對象(基於MongoDB),基於BaseApiController,需要自定義介面處理
    /// </summary>
    [ApiController]
    [Route("api/MongoCustomer")]
    public class MongoCustomerController : BaseApiController
    {
        private ICustomerService _service;

        /// <summary>
        /// 構造函數,並註入基礎介面對象
        /// </summary>
        /// <param name="service"></param>
        public MongoCustomerController(ICustomerService service) 
        {
            this._service = service;
        }

        /// <summary>
        /// 獲取所有記錄
        /// </summary>
        [HttpGet]
        [Route("all")]
        public virtual async Task<ListResultDto<CustomerInfo>> GetAllAsync()
        {
            //檢查用戶是否有許可權,否則拋出MyDenyAccessException異常
            base.CheckAuthorized(AuthorizeKey.ListKey);

            return await _service.GetAllAsync();
        }

 而如果繼承自MongoBaseController ,那麼就會具有基類MongoBaseController 公開的所有控制器方法。 

    /// <summary>
    /// 客戶信息的控制器對象(基於MongoDB),基於MongoBaseController,具有常規CRUD操作介面
    /// </summary>
    [ApiController]
    [Route("api/MongoCustomer2")]
    public class MongoCustomer2Controller : MongoBaseController<CustomerInfo, CustomerPagedDto>
    {
        /// <summary>
        /// 構造函數,並註入基礎介面對象
        /// </summary>
        /// <param name="service"></param>
        public MongoCustomer2Controller(ICustomerService service) : base(service)
        {
        }
    }

 

早幾年前曾經也介紹過該資料庫的相關使用,隨筆如下所示,有需要也可以瞭解下。

基於C#的MongoDB資料庫開發應用(4)--Redis的安裝及使用 伍華聰 2016-01-12  基於C#的MongoDB資料庫開發應用(3)--MongoDB資料庫的C#開發之非同步介面 伍華聰 2016-01-12  基於C#的MongoDB資料庫開發應用(2)--MongoDB資料庫的C#開發 伍華聰 2016-01-06 基於C#的MongoDB資料庫開發應用(1)--MongoDB資料庫的基礎知識和使用 伍華聰 2016-01-05   專註於代碼生成工具、.Net/.NetCore 框架架構及軟體開發,以及各種Vue.js的前端技術應用。著有Winform開發框架/混合式開發框架、微信開發框架、Bootstrap開發框架、ABP開發框架、SqlSugar開發框架等框架產品。
  轉載請註明出處:撰寫人:伍華聰  http://www.iqidi.com 
    

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

-Advertisement-
Play Games
更多相關文章
  • 大數據時代,各行各業對數據採集的需求日益增多,網路爬蟲的運用也更為廣泛,越來越多的人開始學習網路爬蟲這項技術,K哥爬蟲此前已經推出不少爬蟲進階、逆向相關文章,為實現從易到難全方位覆蓋,特設【0基礎學爬蟲】專欄,幫助小白快速入門爬蟲,本期為數據存儲。 概述 上期我們介紹到了文件存儲,講到瞭如何將數據存 ...
  • 函數進階 函數的作用域 作用域又可以被稱為命名空間,指變數起作用的範圍。Python變數作用域可以分為四種,分別為局部作用域、嵌套作用域、全局作用域、內置作用域。 | 作用域 | 英文 | | | | | 局部作用域 | Local | | 嵌套作用域 | Enclosing | | 全局作用域 | ...
  • 一、事件背景: 某天凌晨,一陣急促的鈴聲將我從周公那裡拉了過來,接聽電話後,一臉懵逼。 什麼情況?XX後臺宕機了?當日日誌也不列印了,前端發起的請求,都報超時,重啟後又恢復了,不清楚會不會再次宕機。 出現這種情況,我第一時間想的是為什麼是00:00:00宕機?難道後臺嫌我這個大齡程式員睡得早了? 然 ...
  • Java SpringBoot 通過javax.validation.constraints下的註解,實現入參數據自動驗證 如果碰到 `@NotEmpty` 否則不生效,註意看下 `@RequestBody` 前面是否加上了`@Valid` ...
  • 介面 ​ 介面類型是對其它類型行為的抽象和概括,因為介面類型不會和特定的實現細節綁定在一 起,通過這種抽象的方式我們可以讓我們的函數更加靈活和更具有適應能力 介面的特點 可以包含0個或多個方法的簽名 只定義方法的簽名,不包含實現 實現介面不需要顯式的聲明,只需實現相應方法即可 介面實現 ​ 介面里沒 ...
  • 隨著技術的發展,ASP.NET Core MVC也推出了好長時間,經過不斷的版本更新迭代,已經越來越完善,本系列文章主要講解ASP.NET Core MVC開發B/S系統過程中所涉及到的相關內容,適用於初學者,在校畢業生,或其他想從事ASP.NET Core MVC 系統開發的人員。 經過前幾篇文章... ...
  • 匿名類型在某些場景下使用起來還是比較方便,比如某個類型只會使用一次,那這個時候定義一個 Class 就沒有多少意義,完全可以使用匿名類型來解決,但是在跨項目使用時,還是需要註意避免出現 RuntimeBinderException 問題 問題描述 比如我們有一個 netstandard2.0 類型的 ...
  • C#多線程學習(一) 多線程的相關概念 什麼是進程? 當一個程式開始運行時,它就是一個進程,進程包括運行中的程式和程式所使用到的記憶體和系統資源。 而一個進程又是由多個線程所組成的。 什麼是線程? 線程是程式中的一個執行流,每個線程都有自己的專有寄存器(棧指針、程式計數器等), 但代碼區是共用的,即不 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...