基於C#的MongoDB資料庫開發應用(3)--MongoDB資料庫的C#開發之非同步介面

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

在前面的系列博客中,我曾經介紹過,MongoDB資料庫的C#驅動已經全面支持非同步的處理介面,並且介面的定義幾乎是重寫了。本篇主要介紹MongoDB資料庫的C#驅動的最新介面使用,介紹基於新介面如何實現基礎的增刪改查及分頁等處理,以及如何利用非同步介面實現基類相關的非同步操作。


在前面的系列博客中,我曾經介紹過,MongoDB資料庫的C#驅動已經全面支持非同步的處理介面,並且介面的定義幾乎是重寫了。本篇主要介紹MongoDB資料庫的C#驅動的最新介面使用,介紹基於新介面如何實現基礎的增刪改查及分頁等處理,以及如何利用非同步介面實現基類相關的非同步操作。

MongoDB資料庫驅動在2.2版本(或者是從2.0開始)好像完全改寫了API的介面,因此目前這個版本同時支持兩個版本的API處理,一個是基於MongoDatabase的對象介面,一個是IMongoDatabase的對象介面,前者中規中矩,和我們使用Shell裡面的命令名稱差不多,後者IMongoDatabase的介面是基於非同步的,基本上和前者差別很大,而且介面都提供了非同步的處理操作。

1、MongoDB資料庫C#驅動的新介面

新介面也還是基於資料庫,集合,文檔這樣的處理概念進行封裝,只是它們的介面不再一樣了,我們還是按照前面的做法,定義一個資料庫訪問的基類,對MongoDB資料庫的相關操作封裝在基類裡面,方便使用,同時基類利用泛型對象,實現更強類型的約束及支持,如基類BaseDAL的定義如下所示。

    /// <summary>
    /// 數據訪問層的基類
    /// </summary>
    public partial class BaseDAL<T> where T : BaseEntity, new()

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

基於新介面,如獲取資料庫對象的操作,則利用了IMongoDatabase的介面了,如下所示。

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

相對以前的常規介面,MongoClient對象已經沒有了GetServer的介面了。如果對創建資料庫對象的操作做更好的封裝,可以利用配置文件進行指定的話,那麼方法可以封裝如下所示。

        /// <summary>
        /// 根據資料庫配置信息創建MongoDatabase對象,如果不指定配置信息,則從預設信息創建
        /// </summary>
        /// <param name="databaseName">資料庫名稱,預設空為local</param>
        /// <returns></returns>
        protected virtual IMongoDatabase CreateDatabase()
        {
            string connectionString = null;
            if (!string.IsNullOrEmpty(dbConfigName))
            {
                //從配置文件中獲取對應的連接信息
                connectionString = ConfigurationManager.ConnectionStrings[dbConfigName].ConnectionString;                
            }
            else
            {
                connectionString = defaultConnectionString;
            }

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

            return database;
        }

根據IMongoDatabase 介面,那麼其獲取集合對象的操作如下所示,它使用了另外一個定義IMongoCollection了。

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

2、查詢單個對象實現封裝處理

基於新介面的查詢處理,已經沒有FindOne的方法定義了,只是使用了Find的方法,而且也沒有了Query的對象可以作為條件進行處理,而是採用了新的定義對象FilterDefinition,例如對於根據ID查詢單個對象,介面的實現如下所示。

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

            IMongoCollection<T> collection = GetCollection();
            return collection.Find(s=> s.Id == id).FirstOrDefault();
        }

對於利用FilterDefinition進行查詢的操作,如下所示。

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

我們可以看到,這些都是利用Find方法的不同重載實現不同條件的處理的。

對於這個新介面,非同步是一個重要的改變,那麼它的非同步處理是如何的呢,我們看看上面兩個非同步的實現操作,具體代碼如下所示。

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

            IMongoCollection<T> collection = GetCollection();
            return await collection.FindAsync(s=>s.Id == id).Result.FirstOrDefaultAsync(); 
        }

        /// <summary>
        /// 根據條件查詢資料庫,如果存在返回第一個對象(非同步)
        /// </summary>
        /// <param name="query">條件表達式</param>
        /// <returns>存在則返回指定的第一個對象,否則返回預設值</returns>
        public virtual async Task<T> FindSingleAsync(FilterDefinition<T> query)
        {
            return await GetQueryable(query).SingleOrDefaultAsync();
        }

我們看到,上面的Collection或者GetQueryable(query)返回的對象,都提供給了以Async結尾的非同步方法,因此對非同步的封裝也是非常方便的,上面的GetQueryable(query)是另外一個公共的實現方法,具體代碼如下所示。

        /// <summary>
        /// 返回可查詢的記錄源
        /// </summary>
        /// <param name="query">查詢條件</param>
        /// <returns></returns>
        public virtual IFindFluent<T, T> GetQueryable(FilterDefinition<T> query)
        {
            return GetQueryable(query, this.SortPropertyName, this.IsDescending);
        }
        /// <summary>
        /// 根據條件表達式返回可查詢的記錄源
        /// </summary>
        /// <param name="query">查詢條件</param>
        /// <param name="sortPropertyName">排序表達式</param>
        /// <param name="isDescending">如果為true則為降序,否則為升序</param>
        /// <returns></returns>
        public virtual IFindFluent<T,T> GetQueryable(FilterDefinition<T> query, string sortPropertyName, bool isDescending = true)
        {
            IMongoCollection<T> collection = GetCollection();
            IFindFluent<T, T> queryable = collection.Find(query);

            var sort = this.IsDescending ? Builders<T>.Sort.Descending(this.SortPropertyName) : Builders<T>.Sort.Ascending(this.SortPropertyName);
            return queryable.Sort(sort);
        }

我們可以看到,它返回了IFindFluent<T, T>的對象,這個和以前返回的IMongoQuery對象又有不同,基本上,使用最新的介面,所有的實現都不太一樣,這也是因為MongoDB還在不停變化之中有關。

3、GetQueryable幾種方式

為了簡化代碼,方便使用,我們對獲取MongoDB的LINQ方式的處理做了簡單的封裝,提供了幾個GetQueryable的方式,具體代碼如下所示。

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

            return query.OrderBy(this.SortPropertyName, this.IsDescending);
        }
        /// <summary>
        /// 根據條件表達式返回可查詢的記錄源
        /// </summary>
        /// <param name="match">查詢條件</param>
        /// <param name="orderByProperty">排序表達式</param>
        /// <param name="isDescending">如果為true則為降序,否則為升序</param>
        /// <returns></returns>
        public virtual IQueryable<T> GetQueryable<TKey>(Expression<Func<T, bool>> match, Expression<Func<T, TKey>> orderByProperty, bool isDescending = true)
        {
            IMongoCollection<T> collection = GetCollection();
            IQueryable<T> query = collection.AsQueryable();

            if (match != null)
            {
                query = query.Where(match);
            }

            if (orderByProperty != null)
            {
                query = isDescending ? query.OrderByDescending(orderByProperty) : query.OrderBy(orderByProperty);
            }
            else
            {
                query = query.OrderBy(this.SortPropertyName, isDescending);
            }
            return query;
        }

以及基於FilterDefinition的條件處理,並返回IFindFluent<T,T>介面對象的代碼如下所示。

        /// <summary>
        /// 根據條件表達式返回可查詢的記錄源
        /// </summary>
        /// <param name="query">查詢條件</param>
        /// <param name="sortPropertyName">排序表達式</param>
        /// <param name="isDescending">如果為true則為降序,否則為升序</param>
        /// <returns></returns>
        public virtual IFindFluent<T,T> GetQueryable(FilterDefinition<T> query, string sortPropertyName, bool isDescending = true)
        {
            IMongoCollection<T> collection = GetCollection();
            IFindFluent<T, T> queryable = collection.Find(query);

            var sort = this.IsDescending ? Builders<T>.Sort.Descending(this.SortPropertyName) : Builders<T>.Sort.Ascending(this.SortPropertyName);
            return queryable.Sort(sort);
        }

4、集合的查詢操作封裝處理

基於上面的封裝,對結合的查詢,也是基於不同的條件進行處理,返回對應的列表的處理方式, 最簡單的是利用GetQueryable方式進行處理,代碼如下所示。

        /// <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="match">條件表達式</param>
        /// <returns>指定對象的集合</returns>
        public virtual IList<T> Find(FilterDefinition<T> query)
        {
            return GetQueryable(query).ToList();
        }

以及對排序欄位,以及升降序的處理操作如下所示。

        /// <summary>
        /// 根據條件查詢資料庫,並返回對象集合
        /// </summary>
        /// <param name="match">條件表達式</param>
        /// <param name="orderByProperty">排序表達式</param>
        /// <param name="isDescending">如果為true則為降序,否則為升序</param>
        /// <returns></returns>
        public virtual IList<T> Find<TKey>(Expression<Func<T, bool>> match, Expression<Func<T, TKey>> orderByProperty, bool isDescending = true)
        {
            return GetQueryable<TKey>(match, orderByProperty, isDescending).ToList();
        }

        /// <summary>
        /// 根據條件查詢資料庫,並返回對象集合
        /// </summary>
        /// <param name="query">條件表達式</param>
        /// <param name="orderByProperty">排序欄位</param>
        /// <param name="isDescending">如果為true則為降序,否則為升序</param>
        /// <returns></returns>
        public virtual IList<T> Find<TKey>(FilterDefinition<T> query, string orderByProperty, bool isDescending = true)
        {
            return GetQueryable(query, orderByProperty, isDescending).ToList();
        }

以及利用這些條件進行分頁的處理代碼如下所示。

        /// <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(FilterDefinition<T> query, PagerInfo info)
        {
            int pageindex = (info.CurrenetPageIndex < 1) ? 1 : info.CurrenetPageIndex;
            int pageSize = (info.PageSize <= 0) ? 20 : info.PageSize;

            int excludedRows = (pageindex - 1) * pageSize;

            var find = GetQueryable(query);
            info.RecordCount = (int)find.Count();

            return find.Skip(excludedRows).Limit(pageSize).ToList();
        }

對於非同步的封裝處理,基本上也和上面的操作差不多,例如對於基礎的查詢,非同步操作封裝如下所示。

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

        /// <summary>
        /// 根據條件查詢資料庫,並返回對象集合
        /// </summary>
        /// <param name="query">條件表達式</param>
        /// <returns>指定對象的集合</returns>
        public virtual async Task<IList<T>> FindAsync(FilterDefinition<T> query)
        {
            return await GetQueryable(query).ToListAsync();
        }

複雜一點的分頁處理操作代碼封裝如下所示。

        /// <summary>
        /// 根據條件查詢資料庫,並返回對象集合(用於分頁數據顯示)
        /// </summary>
        /// <param name="match">條件表達式</param>
        /// <param name="info">分頁實體</param>
        /// <returns>指定對象的集合</returns>
        public virtual async Task<IList<T>> FindWithPagerAsync(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();

            var result = query.Skip(excludedRows).Take(pageSize).ToList();
            return await Task.FromResult(result);
        }

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

            int excludedRows = (pageindex - 1) * pageSize;

            var queryable = GetQueryable(query);
            info.RecordCount = (int)queryable.Count();

            return await queryable.Skip(excludedRows).Limit(pageSize).ToListAsync();
        }

5、增刪改方法封裝處理

對於常規的增刪改操作,在新的MongoDB資料庫驅動裡面也修改了名稱,使用的時候也需要進行調整處理了。

        /// <summary>
        /// 插入指定對象到資料庫中
        /// </summary>
        /// <param name="t">指定的對象</param>
        public virtual void Insert(T t)
        {
            ArgumentValidation.CheckForNullReference(t, "傳入的對象t為空");

            IMongoCollection<T> collection = GetCollection();
            collection.InsertOne(t);
        }

非同步的操作實現如下所示。

        /// <summary>
        /// 插入指定對象到資料庫中
        /// </summary>
        /// <param name="t">指定的對象</param>
        public virtual async Task InsertAsync(T t)
        {
            ArgumentValidation.CheckForNullReference(t, "傳入的對象t為空");

            IMongoCollection<T> collection = GetCollection();
            await collection.InsertOneAsync(t);
        }

批量插入記錄的操作如下所示。

        /// <summary>
        /// 插入指定對象集合到資料庫中
        /// </summary>
        /// <param name="list">指定的對象集合</param>
        public virtual void InsertBatch(IEnumerable<T> list)
        {
            ArgumentValidation.CheckForNullReference(list, "傳入的對象list為空");

            IMongoCollection<T> collection = GetCollection();
            collection.InsertMany(list);
        }

對應的非同步操作處理如下所示,這些都是利用原生支持的非同步處理介面實現的。

        /// <summary>
        /// 插入指定對象集合到資料庫中
        /// </summary>
        /// <param name="list">指定的對象集合</param>
        public virtual async Task InsertBatchAsync(IEnumerable<T> list)
        {
            ArgumentValidation.CheckForNullReference(list, "傳入的對象list為空");

            IMongoCollection<T> collection = GetCollection();
            await collection.InsertManyAsync(list);
        }

更新操作,有一種整個替換更新,還有一個是部分更新,它們兩者是有區別的,如對於替換更新的操作,它的介面封裝處理如下所示

        /// <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;
            IMongoCollection<T> collection = GetCollection();
            //使用 IsUpsert = true ,如果沒有記錄則寫入
            var update = collection.ReplaceOne(s => s.Id == id, t, new UpdateOptions() { IsUpsert = true });
            result = update != null && update.ModifiedCount > 0;

            return result;
        }

如果對於部分欄位的更新,那麼操作如下所示 ,主要是利用UpdateDefinition對象來指定需要更新那些欄位屬性及值等信息。

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

            IMongoCollection<T> collection = GetCollection();
            var result = collection.UpdateOne(s => s.Id == id, update, new UpdateOptions() { IsUpsert = true });
            return result != null && result.ModifiedCount > 0;
        }

上面的非同步更新操作如下所示。

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

            IMongoCollection<T> collection = GetCollection();
            var result = await collection.UpdateOneAsync(s => s.Id == id, update, new UpdateOptions() { IsUpsert = true });

            var sucess = result != null && result.ModifiedCount > 0;
            return await Task.FromResult(sucess);
        }

刪除的操作也是類似的了,基本上和上面的處理方式接近,順便列出來供參考學習。

        /// <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為空");

            IMongoCollection<T> collection = GetCollection();
            var result = collection.DeleteOne(s=> s.Id == id);
            return result != null && result.DeletedCount > 0;
        }

        /// <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為空");

            IMongoCollection<T> collection = GetCollection();
            var query = Query.In("_id", new BsonArray(idList));
            var result = collection.DeleteMany(s => idList.Contains(s.Id));
            return result != null && result.DeletedCount > 0;
        }

如果根據條件的刪除,也可以利用條件定義的兩種方式,具體代碼如下所示。

        /// <summary>
        /// 根據指定條件,從資料庫中刪除指定對象
        /// </summary>
        /// <param name="match">條件表達式</param>
        /// <returns>執行成功返回<c>true</c>,否則為<c>false</c></returns>
        public virtual bool DeleteByExpression(Expression<Func<T, bool>> match)
        {
            IMongoCollection<T> collection = GetCollection();
            collection.AsQueryable().Where(match).ToList().ForEach(s => collection.DeleteOne(t => t.Id == s.Id));
            return true;
        }

        /// <summary>
        /// 根據指定條件,從資料庫中刪除指定對象
        /// </summary>
        /// <param name="match">條件表達式</param>
        /// <returns>執行成功返回<c>true</c>,否則為<c>false</c></returns>
        public virtual bool DeleteByQ

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

-Advertisement-
Play Games
更多相關文章
  • Web大前端時代之:HTML5+CSS3入門系列:http://www.cnblogs.com/dunitian/p/5121725.html1.結構元素 可以理解為語義話標記,比如:以前這麼寫 現在偷懶寫: 1.header頭部區域,包含對主頁的介紹 標簽定義文檔的頁眉(介紹信息) 2.nav導....
  • 註釋:VS2010是(Ctrl+E,C),VS2012是(Ctrl+K, Ctrl+C)反註釋:VS2010是(Ctrl+E,U),VS2012是(Ctrl+K, Ctrl+U)
  • 前言:如果我們要寫好我們的單元測試,可能我們要有好的佈局,也要規劃好如何去創建單元測試的類,單元測試的方法,下麵簡單的說一下。1:分開集成測試和單元測試如果我們把集成測試和單元測試放在一起如果出現問題可能出現的原因比較多那麼我們直接進行分離,建立2套類庫。如下圖2:將測試類映射到測試代碼2.1:每一...
  • (6665.900)一個例子用到了函數Formatnumber()的所有參數:第一個參數(-6665.8999)指定了要進行格式化的數字。第二個參數(3)指定了小數點後顯示的位數。第三個參數(-1)指定了是否顯示前導的零。第四個參數(-1)指定是否對負數使用括弧。最後一個參數(0)指定是否顯示分隔符...
  • 現在有很多網站或系統需要在服務端定時做某件事情,如每天早上8點半清理資料庫中的無效數據等等,Demo 具體實現步驟如下:0.先看解決方案截圖1.創建ASP.NET項目TimedTask,然後新建一個全局應用程式類文件 Global.asax2.然後在Application_Start 事件中 啟動定...
  • Response.Write和Response.Redirect一起用的時候就會這樣,write腳本和redirect腳本不能同時使用,這樣不會執行腳本,最好使用ClientScript改進方法:方法一:Page.ClientScript.RegisterClientScriptBlock(this...
  • Web大前端時代之:HTML5+CSS3入門系列:http://www.cnblogs.com/dunitian/p/5121725.html文檔申明 字元編碼(UTF-8) 版本相容 1.省略引號:當屬性值不包括 、=、單引號、雙引號、空字元串時,屬性兩邊的引號可以省略: 2.省略屬性值具有...
  • 最近項目用到ini文件,讀取ini文件,方法如下:using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Collections.Specialized;using ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...