2023年11月28日 星期二

.NET8 Maui 變更應用程式狀態列 Status Bar 的顏色

.NET8 Maui 變更應用程式狀態列 Status Bar 的顏色

.NET8 Maui 變更應用程式狀態列 Status Bar 的顏色

在 Android 或者 iOS 的應用程式中,狀態列 Status Bar 是一個很重要的元件,它會顯示出目前的網路狀態、電池電量、時間等等的資訊,而且,它的顏色也會影響到應用程式的外觀,所以,如果能夠變更狀態列的顏色,將會是一件很有趣的事情。

在上面的畫面截圖,為採用 .NET 8 MAUI 建立的專案,並且在 Android 模擬器上執行的結果,在螢幕畫面的最上方將會看到一條狀態列,可以看到,狀態列的背景顏色是紫色的,文字或者圖示的顏色則是白色的,此時,在這個預設的應用程式啟動的時候,是有導航頁面的,這裡可以從最上方有個 Home 文字所在的位置看到底色為白色的導航頁面所在位置,而在導航頁面的下方,則是這個當前頁面,也稱為 內容頁面 ContentPage 所顯示的區域,這裡會看到有個圖片與 Hello, World! 出現在手機螢幕上。

一般來說,導航頁面與內容頁面將會依據應用程式的設計,而有不同的顏色,有些時候會將這兩個頁面背景顏色設定為同一種顏色,想要做到這樣的效果,可以直接透過 ContentPage 內容頁面的 XAML 檔案內來做宣告,便可以變更成為不同的顏色,但是,狀態列的顏色,則是由應用程式的設定所決定的,而無法直接透過預設 XAML 提供的功能,來做到這樣的效果。

在這篇文章將會說明如何進行狀態列的顏色變更的設計方法。

這個範例程式一開始執行,將會出現如下圖

對於狀態列、導航頁面、內容頁面的顏色,都是採用紅色,而在內容頁面裡面,將會有個按鈕,按下這個按鈕,將會變更狀態列的顏色,變更為綠色,而導航頁面與內容頁面的顏色,則是不會變更;如下圖所示

建立測試專案

為了能夠完成這份文件所提到的事情,需要將電腦上的 Visual Studio 2022 升級到 17.8 以上的版本,也就是,這台電腦上必須要有安裝 .NET 8 SDK。

  • 打開 Visual Studio 2022 IDE 應用程式
  • 從 [Visual Studio 2022] 對話窗中,點選右下方的 [建立新的專案] 按鈕
  • 在 [建立新專案] 對話窗右半部
    • 切換 [所有語言 (L)] 下拉選單控制項為 [C#]
    • 切換 [所有專案類型 (T)] 下拉選單控制項為 [MAUI]
  • 在中間的專案範本清單中,找到並且點選 [.NET MAUI 應用程式] 專案範本選項

    此專案可用於建立適用於 iOS、Android、Mac Catalyst、Tizen 和 WinUI 的 .NET MAUI 應用程式。

  • 點選右下角的 [下一步] 按鈕
  • 在 [設定新的專案] 對話窗
  • 找到 [專案名稱] 欄位,輸入 MX01 作為專案名稱
  • 在剛剛輸入的 [專案名稱] 欄位下方,確認沒有勾選 [將解決方案與專案至於相同目錄中] 這個檢查盒控制項
  • 點選右下角的 [下一步] 按鈕
  • 現在將會看到 [其他資訊] 對話窗
  • 在 [架構] 欄位中,請選擇最新的開發框架,這裡選擇的 [架構] 是 : .NET 8.0 (長期支援)
  • 請點選右下角的 [建立] 按鈕

稍微等候一下,這個主控台專案將會建立完成

安裝要用到的 NuGet 開發套件

因為開發此專案時會用到這些 NuGet 套件,請依照底下說明,將需要用到的 NuGet 套件安裝起來。

安裝 CommunityToolkit.Mvvm 套件

CommunityToolkit.Mvvm 是一個現代、快速和模組化的 MVVM 庫,適用於 .NET。它是 .NET Community Toolkits 的一部分,這是由 .NET 社區開發的開源庫集合。CommunityToolkit.Mvvm 基於以下原則構建:

  • 跨平台和運行時無關: CommunityToolkit.Mvvm 可與 .NET Standard 2.0、.NET Standard 2.1 和 net6.0 一起使用。它還適用於 WPF、Xamarin.Forms 和 UWP。
  • 模塊化: CommunityToolkit.Mvvm 是一個模塊化庫,這意味著您只能包含庫中所需的部分。這使它成為一個輕量級且易於使用的庫。
  • 可擴展: CommunityToolkit.Mvvm 是可擴展的,這意味著您可以為庫創建自己的擴展。這使它成為一個靈活的庫,可以根據您的特定需求進行調整。

CommunityToolkit.Mvvm 包括以下功能:

  • 消息傳遞: CommunityToolkit.Mvvm 提供了一個消息傳遞系統,可讓您在應用程序的不同部分之間進行通信。
  • 命令: CommunityToolkit.Mvvm 提供了一個命令系統,可讓您將 UI 元素綁定到視圖模型中的方法。
  • 可觀察對象: CommunityToolkit.Mvvm 提供了一個 ObservableObject 類,可讓您創建可以通知其觀察者其屬性更改的對象。
  • IObservableRecipient: CommunityToolkit.Mvvm 提供了一個 IObservableRecipient 接口,可讓您創建可以接收消息的視圖模型。

請依照底下說明操作步驟,將這個套件安裝到專案內

  • 滑鼠右擊 [方案總管] 視窗內的 [專案節點] 下方的 [相依性] 節點
  • 從彈出功能表清單中,點選 [管理 NuGet 套件] 這個功能選項清單
  • 此時,將會看到 [NuGet: MX01] 視窗
  • 切換此視窗的標籤頁次到名稱為 [瀏覽] 這個標籤頁次
  • 在左上方找到一個搜尋文字輸入盒,在此輸入 CommunityToolkit.Mvvm
  • 稍待一會,將會在下方看到這個套件被搜尋出來
  • 點選 [CommunityToolkit.Mvvm] 套件名稱
  • 在視窗右方,將會看到該套件詳細說明的內容,其中,右上方有的 [安裝] 按鈕
  • 點選這個 [安裝] 按鈕,將這個套件安裝到專案內

安裝 CommunityToolkit.Maui 套件

CommunityToolkit.Maui 是為 .NET MAUI 開發的一個社群工具包,它包含了一系列可重複使用的元素,包括動畫、行為、轉換器、效果和協助程式。這些元素可以幫助開發人員更輕鬆地建立 .NET MAUI 應用程式,並提高應用程式的功能和可用性。

CommunityToolkit.Maui 的功能包括:

  • 動畫:包含一系列動畫,可用於在應用程式中創建動態效果。
  • 行為:包含一系列行為,可用於添加額外的功能到 .NET MAUI 元素。
  • 轉換器:包含一系列轉換器,可用於將數據從一種格式轉換為另一種格式。
  • 效果:包含一系列效果,可用於在應用程式中添加視覺效果。
  • 協助程式:包含一系列協助程式,可用於簡化 .NET MAUI 開發。

請依照底下說明操作步驟,將這個套件安裝到專案內

  • 滑鼠右擊 [方案總管] 視窗內的 [專案節點] 下方的 [相依性] 節點
  • 從彈出功能表清單中,點選 [管理 NuGet 套件] 這個功能選項清單
  • 此時,將會看到 [NuGet: MX01] 視窗
  • 切換此視窗的標籤頁次到名稱為 [瀏覽] 這個標籤頁次
  • 在左上方找到一個搜尋文字輸入盒,在此輸入 CommunityToolkit.Maui
  • 稍待一會,將會在下方看到這個套件被搜尋出來
  • 點選 [CommunityToolkit.Maui] 套件名稱
  • 在視窗右方,將會看到該套件詳細說明的內容,其中,右上方有的 [安裝] 按鈕
  • 點選這個 [安裝] 按鈕,將這個套件安裝到專案內
  • 安裝完成後,將會出現視窗 [Readme.txt] 這個視窗,說明這個套件的設定用法

.NET MAUI Community Toolkit

Initializing

In order to use the .NET MAUI Community Toolkit you need to call the extension method in your MauiProgram.cs file as follows:

using CommunityToolkit.Maui;

public static class MauiProgram
{
	public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
		builder
			.UseMauiApp<App>()
			// Initialize the .NET MAUI Community Toolkit by adding the below line of code
			.UseMauiCommunityToolkit()
			// After initializing the .NET MAUI Community Toolkit, optionally add additional fonts
			.ConfigureFonts(fonts =>
			{
				fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
				fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
			});

		// Continue initializing your .NET MAUI App here

		return builder.Build();
	}
}

XAML usage

In order to make use of the toolkit within XAML you can use this namespace:

xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"

Further information

For more information please visit:

進行變更狀態列顏色的程式設計

  • 依據 CommunityToolkit.Maui 的說明文件
  • 在專案根目錄下找到並且打開 MauiProgram.cs 檔案
  • 找到 .UseMauiApp<App>() 表示式,在其下方加入這個表示式 .UseMauiCommunityToolkit() ,宣告 CommunityToolkit.Maui 會用到的相關服務,需要註冊到 DI Container 相依性注入容器內
  • 滑鼠右擊專案節點
  • 從功能表清單中,點選 [加入] > [類別] 的 選項
  • 在 [新增項目] 對話窗內,確認要建立的型別為 [類別]
  • 在該對話窗下方的名稱欄位,輸入 [MainPageViewModel.cs]
  • 點選右下方的 [新增] 按鈕,建立起這個 ViewModel 類別
  • 使用底下程式碼替換掉剛剛建立的類別檔案內容
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace MX01;

public partial class MainPageViewModel : ObservableObject
{
    [RelayCommand]
    void ChangeStatuBarColor()
    {
        CommunityToolkit.Maui.Core.Platform
            .StatusBar.SetColor(Colors.Green);
        CommunityToolkit.Maui.Core.Platform
            .StatusBar.SetStyle(CommunityToolkit.Maui.Core.StatusBarStyle.LightContent);
    }
}
  • 在這裡,這個 MainPageViewModel 類別,依據 [CommunityToolkit.Mvvm] 套件規範,修正了類別為 [partial] 部分類別,並且繼承了 [ObservableObject] 這個類別
  • 有了這個設定之後,就可以在這個類別內進行一般資料、命令、集合物件的資料綁定宣告了
  • 在此,建立了一個方法 [void ChangeStatuBarColor()] ,並且在這個方法上方,加入了 [RelayCommand] 這個屬性宣告,表示這個方法將可以用於在 XAML 中進行綁定到 XAML 命令屬性上,此時,在 XAML 中,將會看到一個 [ChangeStatuBarColorCommand] 出現在 {Binding } 可以選擇清單內
  • 這裡展示了,如何透過 C# 程式碼,進行狀態列的背景顏色設定 CommunityToolkit.Maui.Core.Platform.StatusBar.SetColor(Colors.Green); 與前景顏色設定 CommunityToolkit.Maui.Core.Platform.StatusBar.SetStyle(CommunityToolkit.Maui.Core.StatusBarStyle.LightContent);
  • 現在要來這對 View & ViewModel 註冊到相依注入容器內
  • 在專案根目錄下找到並且打開 MauiProgram.cs 檔案
  • 找到 #if DEBUG 前置處理器敘述
  • 在其上方加入底下程式碼,已完成 [MainPage] & [MainPageViewModel] 這兩個類別的注入註冊
builder.Services.AddTransient<MainPageViewModel>();
builder.Services.AddTransient<MainPage>();
  • 在專案根目錄下找到 [MainPage.xaml] 檔案,在這個檔案的下方有個 [MainPage.xaml.cs] 檔案,雙擊這個節點,打開這個檔案
  • 將這個檔案內容 [MainPage.xaml.cs] 替換為底下程式碼
namespace MX01;

public partial class MainPage : ContentPage
{
    public MainPage(MainPageViewModel mainPageViewModel)
    {
        InitializeComponent();

        BindingContext = mainPageViewModel;
    }
}
  • 在這裡會將原先專案範本產生的事件與欄位都刪除掉,並且在建構式內,要求注入 [MainPageViewModel] 物件,而後將這個 [MainPageViewModel] 物件指定到該內容頁面的 [BindingContext] 屬性內
  • 現在要來修正 [MainPage.xaml]
  • 在專案根目錄下找到並且打開 [MainPage.xaml] 檔案
  • 將這個檔案內容替換為底下程式碼
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MX01.MainPage"
             Title="變更狀態列顏色"
             xmlns:vm="clr-namespace:MX01"
             x:DataType="vm:MainPageViewModel"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             BackgroundColor="Red"
             Shell.BackgroundColor="Red"
             Shell.TitleColor="White">

    <ContentPage.Behaviors>
        <toolkit:StatusBarBehavior StatusBarColor="Red"
                                   StatusBarStyle="LightContent"/>
    </ContentPage.Behaviors>

    <Grid>
        <VerticalStackLayout
            Padding="30,0"
            Spacing="25">

            <Button
                Text="狀態列變色" 
                HorizontalOptions="Fill"
                Command="{Binding ChangeStatuBarColorCommand}"/>
        </VerticalStackLayout>
    </Grid>

</ContentPage>
  • 對於這個內容頁面,將會在 [ContentPage] 節點內,使用 BackgroundColor="Red" 屬性宣告語法,宣告內容頁面的背景顏色為紅色
  • 對於導航頁面的背景顏色,將會同樣在 [ContentPage] 節點內,使用 Shell.BackgroundColor="Red" 附加屬性語法,宣告導航頁面的背景顏色為紅色,另外,透過 Shell.TitleColor="White" 宣告導航頁面的文字為白色
  • 在 [ContentPage] 內,加入一個行為宣告,這裡將會在 [ContentPage.Behaviors] 項目屬性內,加入 <toolkit:StatusBarBehavior StatusBarColor="Red" StatusBarStyle="LightContent"/> 這樣的敘述,這裡將會引用[CommunityToolkit.Maui] 套件內提供的一個行為,該行為可以用來設定狀態列的背景顏色與文字前景顏色
  • 對於按鈕這個項目 <Button Text="狀態列變色" HorizontalOptions="Fill" Command="{Binding ChangeStatuBarColorCommand}"/> 將會使用 [Command] 這個屬性,用來綁定到 ViewModel 內設計的 [ChangeStatuBarColorCommand] 命令

 




2023年11月23日 星期四

MongoDB 系列 - 使用 C# 來刪除存在於 Docker 容器內的 MongoDB 資料庫內的文件

MongoDB 系列 - 使用 C# 來刪除存在於 Docker 容器內的 MongoDB 資料庫內的文件

對於資料庫操作的 CRUD 應用之第四個部分,也是最後一個,那就是 D Delete 這個英文字,中文翻譯過來就是刪除,因此在篇文章將會要來探討這部分的程式設計做法。

經過前篇文章 MongoDB 系列 - 使用 C# 來刪除存在於 Docker 容器內的 MongoDB 資料庫內的文件 介紹,學會了如何透過 Filter 或者 .NET Linq 的方式來進行查詢出資料庫內符合條件的文件。

這樣的技術將會在要刪除 MongoDB 文件的時候用到,因為,當要進行 MongoDB 文件刪除的時候,需要指定刪除條件,也就是說要指定會影響到那些文件,因此,在這裡將會需要指定一個 Filter 物件。

在這篇文章中,也會使用 Linq 作為查詢條件,讓在刪除文件的時候,可以使用 Linq 表示式來進行查詢,不過,此時需要使用 C# 強型別的方式來進行設計。

另外,在 MongoDB 的刪除 API 中,會有刪除一筆文件或者是刪除多筆文件的操作,因此,在這裡將會介紹如何透過 C# 程式碼來進行這兩種不同的刪除操作。最後將會透過查詢方式,重新取得最新的文件內容,來驗證這些文件是否已經被刪除過了。

建立測試專案

請依照底下的操作,建立起這篇文章需要用到的練習專案

  • 打開 Visual Studio 2022 IDE 應用程式
  • 從 [Visual Studio 2022] 對話窗中,點選右下方的 [建立新的專案] 按鈕
  • 在 [建立新專案] 對話窗右半部
    • 切換 [所有語言 (L)] 下拉選單控制項為 [C#]
    • 切換 [所有專案類型 (T)] 下拉選單控制項為 [主控台]
  • 在中間的專案範本清單中,找到並且點選 [主控台應用程式] 專案範本選項

    專案,用於建立可在 Windows、Linux 及 macOS 於 .NET 執行的命令列應用程式

  • 點選右下角的 [下一步] 按鈕
  • 在 [設定新的專案] 對話窗
  • 找到 [專案名稱] 欄位,輸入 csMongoDBDelete 作為專案名稱
  • 在剛剛輸入的 [專案名稱] 欄位下方,確認沒有勾選 [將解決方案與專案至於相同目錄中] 這個檢查盒控制項
  • 點選右下角的 [下一步] 按鈕
  • 現在將會看到 [其他資訊] 對話窗
  • 在 [架構] 欄位中,請選擇最新的開發框架,這裡選擇的 [架構] 是 : .NET 7.0 (標準字詞支援)
  • 在這個練習中,需要去勾選 [不要使用最上層陳述式(T)] 這個檢查盒控制項

    這裡的這個操作,可以由讀者自行決定是否要勾選這個檢查盒控制項

  • 請點選右下角的 [建立] 按鈕

稍微等候一下,這個主控台專案將會建立完成

安裝要用到的 NuGet 開發套件

因為開發此專案時會用到這些 NuGet 套件,請依照底下說明,將需要用到的 NuGet 套件安裝起來。

安裝 MongoDB.Driver 套件

  • 滑鼠右擊 [方案總管] 視窗內的 [專案節點] 下方的 [相依性] 節點
  • 從彈出功能表清單中,點選 [管理 NuGet 套件] 這個功能選項清單
  • 此時,將會看到 [NuGet: csMongoDBDelete] 視窗
  • 切換此視窗的標籤頁次到名稱為 [瀏覽] 這個標籤頁次
  • 在左上方找到一個搜尋文字輸入盒,在此輸入 MongoDB.Driver
  • 在視窗右方,將會看到該套件詳細說明的內容,其中,右上方有的 [安裝] 按鈕
  • 點選這個 [安裝] 按鈕,將這個套件安裝到專案內

建立要使用的程式碼

  • 在 [方案總管] 內找到並且開啟 [Program.cs] 檔案這個節點
  • 使用底下 C# 程式碼,將原本的程式碼取代掉
using MongoDB.Bson;
using MongoDB.Driver;
using System.Diagnostics;

namespace csMongoDBDelete;


// MongoDB 的 Blog 文件資料結構
public class Blog
{
    public ObjectId Id { get; set; }
    public int BlogId { get; set; }
    public string Title { get; set; } = string.Empty;
    public string Tag { get; set; } = string.Empty;
    public string Content { get; set; } = string.Empty;
    public DateTime CreateAt { get; set; } = DateTime.Now;
    public DateTime UpdateAt { get; set; } = DateTime.Now;
}

internal class Program
{
    public static async Task Main(string[] args)
    {
        #region 準備相關設定要進行與雲端 MongoDB 連線用的參數與物件
        // 使用 Environment 來抓取環境變數設定的 帳號與密碼
        string MongoDBAccount = Environment.GetEnvironmentVariable("MongoDBAccount");
        string MongoDBPassword = Environment.GetEnvironmentVariable("MongoDBPassword");

        // 使用 MongoDB Atlas 來連線
        //var mongoUri = $"mongodb+srv://{MongoDBAccount}:{MongoDBPassword}@vulcanmongo.hptf95d.mongodb.net/?retryWrites=true&w=majority";
        var mongoUri = $"mongodb://localhost:27017/?retryWrites=true&w=majority";

        // 宣告一個 MongoDB Client 變數
        IMongoClient client;

        // 宣告一個 MongoDB Database 變數
        IMongoDatabase database;

        // 宣告一個 MongoDB Collection 變數
        IMongoCollection<Blog> collection;

        // 連線到 MongoDB Atlas
        client = new MongoClient(mongoUri);
        #endregion

        #region 進行各種不同 MongoDB 資料庫的 Collection 查詢作法
        #region 建立操作 MogoDB 資料庫與Collection 物件
        // 宣告一個 Database Name 與 Collection Name
        var dbName = "MyCrud";
        var collectionName = "BlogForDelete";

        // 取得 MongoDB Collection
        database = client.GetDatabase(dbName);

        #region 先行刪除這個測試用的 Collection
        await database.DropCollectionAsync(collectionName);
        #endregion

        collection = database.GetCollection<Blog>(collectionName);

        Stopwatch stopwatch = new Stopwatch();
        #endregion

        #region 建立準備要進行刪除用的測試文件
        #region 一次新增 10 筆文件
        Console.WriteLine();
        await Console.Out.WriteLineAsync($"建立準備要進行刪除用的測試文件");
        stopwatch.Restart();
        List<Blog> blogs = new List<Blog>();
        stopwatch.Restart();
        for (int i = 0; i < 10; i++)
        {
            // 宣告一個 Blog 物件
            Blog blog = new Blog
            {
                BlogId = i,
                Title = $"Hello MongoDB{i}",
                Tag = $"C#",
                Content = $"Hello MongoDB{i%3}",
                CreateAt = DateTime.Now.AddDays(i).Date,
                UpdateAt = DateTime.Now.AddDays(i).Date
            };
            blogs.Add(blog);
        }
        // 進行批次新增 Blog 資料
        collection.InsertMany(blogs);
        stopwatch.Stop();
        // 顯示需要耗費時間
        Console.WriteLine($"一次新增 10 筆文件需要 {stopwatch.ElapsedMilliseconds} ms");
        #endregion
        #endregion

        #region 找出符合刪除條件的文件,並進行刪除一筆文件
        Console.WriteLine();
        await Console.Out.WriteLineAsync($"找出符合刪除條件的文件,並進行刪除一筆文件");
        await Console.Out.WriteLineAsync($"Collection 內的所有文件");
        var byLinqCollectionWithClass = await collection.AsQueryable().ToListAsync();
        foreach (var item in byLinqCollectionWithClass)
        {
            Console.WriteLine($"  {item.Id} / {item.Title} / {item.Content}");
        }

        stopwatch.Restart();

        var filter1 = Builders<Blog>.Filter.Eq(r => r.Title, "Hello MongoDB5");
        var updateResult = await collection.DeleteOneAsync(filter1);

        stopwatch.Stop();
        // 顯示需要耗費時間
        Console.WriteLine($"刪除花費 {stopwatch.ElapsedMilliseconds} ms");
        await Console.Out.WriteLineAsync($"Status : {updateResult.IsAcknowledged} / {updateResult.DeletedCount}");
        await Console.Out.WriteLineAsync($"重新列出 Collection 內的所有文件");
        byLinqCollectionWithClass = await collection.AsQueryable().ToListAsync();
        foreach (var item in byLinqCollectionWithClass)
        {
            Console.WriteLine($"  {item.Id} / {item.Title} / {item.Content}");
        }
        #endregion

        #region 找出符合刪除條件的文件,並進行刪除多筆文件 使用 Builders.Filter
        Console.WriteLine();
        Console.WriteLine();
        await Console.Out.WriteLineAsync($"找出符合刪除條件的文件,並進行刪除多筆文件 使用 Builders.Filter");
        await Console.Out.WriteLineAsync($"Collection 內的所有文件");
        byLinqCollectionWithClass = await collection.AsQueryable().ToListAsync();
        foreach (var item in byLinqCollectionWithClass)
        {
            Console.WriteLine($"  {item.Id} / {item.Title} / {item.Content}");
        }

        stopwatch.Restart();

        var filter2 = Builders<Blog>.Filter.Eq(r => r.Content, "Hello MongoDB2");
        var updateResult2 = await collection.DeleteManyAsync(filter2);
        stopwatch.Stop();
        // 顯示需要耗費時間
        Console.WriteLine($"使用 Builders.Filter 刪除花費 {stopwatch.ElapsedMilliseconds} ms");
        await Console.Out.WriteLineAsync($"Status : {updateResult2.IsAcknowledged} / {updateResult2.DeletedCount}");
        await Console.Out.WriteLineAsync($"重新列出 Collection 內的所有文件");
        byLinqCollectionWithClass = await collection.AsQueryable().ToListAsync();
        foreach (var item in byLinqCollectionWithClass)
        {
            Console.WriteLine($"  {item.Id} / {item.Title} / {item.Content}");
        }
        #endregion

        #region 找出符合刪除條件的文件,並進行刪除多筆文件 使用 LINQ
        Console.WriteLine();
        Console.WriteLine();
        await Console.Out.WriteLineAsync($"找出符合刪除條件的文件,並進行刪除多筆文件 使用 LINQ");
        await Console.Out.WriteLineAsync($"Collection 內的所有文件");
        byLinqCollectionWithClass = await collection.AsQueryable().ToListAsync();
        foreach (var item in byLinqCollectionWithClass)
        {
            Console.WriteLine($"  {item.Id} / {item.Title} / {item.Content}");
        }

        stopwatch.Restart();

        var updateResult21 = await collection
            .DeleteManyAsync<Blog>(x => x.Content == "Hello MongoDB0" ||
            x.Title == "Hello MongoDB1");

        stopwatch.Stop();
        // 顯示需要耗費時間
        Console.WriteLine($"使用 Linq 刪除花費 {stopwatch.ElapsedMilliseconds} ms");
        //await Console.Out.WriteLineAsync($"Status : {updateResult21.IsAcknowledged} / {updateResult21.DeletedCount}");
        await Console.Out.WriteLineAsync($"重新列出 Collection 內的所有文件");
        byLinqCollectionWithClass = await collection.AsQueryable().ToListAsync();
        foreach (var item in byLinqCollectionWithClass)
        {
            Console.WriteLine($"  {item.Id} / {item.Title} / {item.Content}");
        }
        #endregion
        #endregion

    }
}
  • 簡單說明這段範例程式碼所要做的事情
    • 先刪除測試用的 Collection
    • 新增10筆文件到剛剛刪除的 Collection
    • 取得所有的文件,列印在螢幕上
    • 使用條件 Title = "Hello MongoDB5" ,刪除一筆 Collection 內的文件
    • 取得所有的文件,列印在螢幕上,確認僅影響到一筆文件
    • 使用的條件為 Content = "Hello MongoDB2" 過濾條件,呼叫刪除多筆 API,刪除 Collection內的多筆文件
    • 取得所有的文件,列印在螢幕上,確認多筆文件是否已經刪除了
    • 最後,不使用 Builders.Filter 來建立一個過濾條件,而是直接在刪除 API 內使用 LINQ 表示式來指定出需要刪除的紀錄條件
    • 這裡使用到這樣的 x.Content == "Hello MongoDB0" || x.Title == "Hello MongoDB1" LINQ 表示式
    • 當然,還是要將 Collection 內的所有文件列印出來,確認是否真的有把指定條件的文件刪除了
  • 在 #region 先行刪除這個測試用的 Collection 區塊內,將會使用 await database.DropCollectionAsync(collectionName); 敘述將這個 BlogForDelete Collection 集合刪除掉,目的是在於要讓這個刪除測試動作,其測試環境變得乾淨
  • 不過,不用擔心這個 Collection 被刪除掉,一旦有文件要新增到這個 Collection 時候,這個 Collection 將會自動重新建立起來
  • 在 #region 建立準備要進行刪除用的測試文件 區段內,將會建立 10 筆型別為 Blog 型別的文件到這個 BlogForDelete Collection 內,不過,對於 Content 這個屬性值,將會使用 $"Hello MongoDB{i%3}" 這樣的表示式來指定成為其值,也就是對於 Content 這個欄位而言,將會是 "Hello MongoDB0" or "Hello MongoDB1" or "Hello MongoDB2" 這三種字串的其中一個。
  • 在 #region 找出符合刪除條件的文件,並進行刪除一筆文件 區塊內,將會使用 var filter1 = Builders<Blog>.Filter.Eq(r => r.Title, "Hello MongoDB5"); 敘述,建立一個 Filter 物件,這個 Filter 物件的條件是 Title 屬性值等於 Hello MongoDB5;這樣的條件在這個測試用的 Collection 內,將只會查詢出僅有一筆文件
  • 最後,使用 var updateResult = await collection.DeleteOneAsync(filter1); 敘述,呼叫 DeleteOneAsync API,將符合 Filter 條件的文件,進行刪除
  • 接下來,將會把這個 Collection 內的所有文件都取出並且顯示在螢幕上,確認剛剛的刪除動作有成功
  • 在 #region 找出符合刪除條件的文件,並進行刪除多筆文件 使用 Builders.Filter 區塊內,將會使用 var filter2 = Builders<Blog>.Filter.Eq(r => r.Content, "Hello MongoDB2"); 敘述,建立一個 Filter 物件,這個 Filter 物件的條件是 Content 屬性值等於 Hello MongoDB2;透過這個 Filter 物件,將會查詢出多筆文件,因為,許多文件內的 Content 欄位內,都有這個字串值。
  • 最後,使用 var updateResult2 = await collection.DeleteManyAsync(filter2); 敘述,呼叫 DeleteManyAsync API,將符合 Filter 條件的文件,進行刪除
  • 接下來,將會把這個 Collection 內的所有文件都取出並且顯示在螢幕上,確認剛剛的刪除動作有成功
  • 在 #region 找出符合刪除條件的文件,並進行刪除多筆文件 使用 LINQ 區塊內,將不需要使用 Builders.Filter 來建立一個過濾物件
  • 最後,呼叫 DeleteManyAsync API,在第一個參數內,使用 LINQ 表示式來指定要查除文件的查詢條件,將符合條件的文件,進行刪除
var updateResult21 = await collection
    .DeleteManyAsync<Blog>(x => x.Content == "Hello MongoDB0" ||
    x.Title == "Hello MongoDB1");
  • 接下來,將會把這個 Collection 內的所有文件都取出並且顯示在螢幕上,確認剛剛的刪除動作有成功
  • 底下將會這個程式碼執行結果
建立準備要進行刪除用的測試文件
一次新增 10 筆文件需要 138 ms

找出符合刪除條件的文件,並進行刪除一筆文件
Collection 內的所有文件
  6552da9f782cea2d1a7089a3 / Hello MongoDB0 / Hello MongoDB0
  6552da9f782cea2d1a7089a4 / Hello MongoDB1 / Hello MongoDB1
  6552da9f782cea2d1a7089a5 / Hello MongoDB2 / Hello MongoDB2
  6552da9f782cea2d1a7089a6 / Hello MongoDB3 / Hello MongoDB0
  6552da9f782cea2d1a7089a7 / Hello MongoDB4 / Hello MongoDB1
  6552da9f782cea2d1a7089a8 / Hello MongoDB5 / Hello MongoDB2
  6552da9f782cea2d1a7089a9 / Hello MongoDB6 / Hello MongoDB0
  6552da9f782cea2d1a7089aa / Hello MongoDB7 / Hello MongoDB1
  6552da9f782cea2d1a7089ab / Hello MongoDB8 / Hello MongoDB2
  6552da9f782cea2d1a7089ac / Hello MongoDB9 / Hello MongoDB0
刪除花費 27 ms
Status : True / 1
重新列出 Collection 內的所有文件
  6552da9f782cea2d1a7089a3 / Hello MongoDB0 / Hello MongoDB0
  6552da9f782cea2d1a7089a4 / Hello MongoDB1 / Hello MongoDB1
  6552da9f782cea2d1a7089a5 / Hello MongoDB2 / Hello MongoDB2
  6552da9f782cea2d1a7089a6 / Hello MongoDB3 / Hello MongoDB0
  6552da9f782cea2d1a7089a7 / Hello MongoDB4 / Hello MongoDB1
  6552da9f782cea2d1a7089a9 / Hello MongoDB6 / Hello MongoDB0
  6552da9f782cea2d1a7089aa / Hello MongoDB7 / Hello MongoDB1
  6552da9f782cea2d1a7089ab / Hello MongoDB8 / Hello MongoDB2
  6552da9f782cea2d1a7089ac / Hello MongoDB9 / Hello MongoDB0


找出符合刪除條件的文件,並進行刪除多筆文件 使用 Builders.Filter
Collection 內的所有文件
  6552da9f782cea2d1a7089a3 / Hello MongoDB0 / Hello MongoDB0
  6552da9f782cea2d1a7089a4 / Hello MongoDB1 / Hello MongoDB1
  6552da9f782cea2d1a7089a5 / Hello MongoDB2 / Hello MongoDB2
  6552da9f782cea2d1a7089a6 / Hello MongoDB3 / Hello MongoDB0
  6552da9f782cea2d1a7089a7 / Hello MongoDB4 / Hello MongoDB1
  6552da9f782cea2d1a7089a9 / Hello MongoDB6 / Hello MongoDB0
  6552da9f782cea2d1a7089aa / Hello MongoDB7 / Hello MongoDB1
  6552da9f782cea2d1a7089ab / Hello MongoDB8 / Hello MongoDB2
  6552da9f782cea2d1a7089ac / Hello MongoDB9 / Hello MongoDB0
使用 Builders.Filter 刪除花費 5 ms
Status : True / 2
重新列出 Collection 內的所有文件
  6552da9f782cea2d1a7089a3 / Hello MongoDB0 / Hello MongoDB0
  6552da9f782cea2d1a7089a4 / Hello MongoDB1 / Hello MongoDB1
  6552da9f782cea2d1a7089a6 / Hello MongoDB3 / Hello MongoDB0
  6552da9f782cea2d1a7089a7 / Hello MongoDB4 / Hello MongoDB1
  6552da9f782cea2d1a7089a9 / Hello MongoDB6 / Hello MongoDB0
  6552da9f782cea2d1a7089aa / Hello MongoDB7 / Hello MongoDB1
  6552da9f782cea2d1a7089ac / Hello MongoDB9 / Hello MongoDB0


找出符合刪除條件的文件,並進行刪除多筆文件 使用 LINQ
Collection 內的所有文件
  6552da9f782cea2d1a7089a3 / Hello MongoDB0 / Hello MongoDB0
  6552da9f782cea2d1a7089a4 / Hello MongoDB1 / Hello MongoDB1
  6552da9f782cea2d1a7089a6 / Hello MongoDB3 / Hello MongoDB0
  6552da9f782cea2d1a7089a7 / Hello MongoDB4 / Hello MongoDB1
  6552da9f782cea2d1a7089a9 / Hello MongoDB6 / Hello MongoDB0
  6552da9f782cea2d1a7089aa / Hello MongoDB7 / Hello MongoDB1
  6552da9f782cea2d1a7089ac / Hello MongoDB9 / Hello MongoDB0
使用 Linq 刪除花費 28 ms
重新列出 Collection 內的所有文件
  6552da9f782cea2d1a7089a7 / Hello MongoDB4 / Hello MongoDB1 

  6552da9f782cea2d1a7089aa / Hello MongoDB7 / Hello MongoDB1