2020年10月23日 星期五

Entity Framework Core 體驗 ChangeTracker 運作模式

Entity Framework Core 體驗 ChangeTracker 運作模式

在上一篇 EF Core 討論文章 EF Core 的 紀錄刪除 ,說明了如何使用 EF Core 來刪除資料庫紀錄的做法。

在這篇文章中,來了解如何使用 EF Core 來進行記錄刪除動作的作法,關於更多這方面的應用,可以參考 ChangeTracker & 追蹤與 No-Tracking 的查詢 這份文件內容。

請按照底下的步驟來進行操作

建立練習專案

  • 打開 Visual Studio 2019

  • 點選 [建立新的專案] 按鈕

  • 在 [建立新專案] 對話窗內,選擇 [Blazor 應用程式] 專案樣板

  • 在 [設定新的專案] 對話窗內,於 [專案名稱] 欄位內輸入 efChangeTracker

  • 在 [建立新的 Blazor 應用程式] 對話窗內,選擇 [Blazor 伺服器應用程式] 這個選項

    在該對話窗右半部的其他選項,可以不用變更

  • 點選 [建立] 按鈕,以便開始建立這個專案

加入 Entity Framework Core 要使用到的 NuGet 套件

  • 滑鼠右擊專案內的 [相依性] 節點
  • 選擇 [管理 NuGet 套件]
  • 點選 [瀏覽] 標籤分頁頁次
  • 在 [搜尋] 文字輸入盒內,輸入 [Microsoft.EntityFrameworkCore.SqlServer]
  • 點選 [安裝] 按鈕以便安裝這個套件
  • 在 [搜尋] 文字輸入盒內,輸入 [Microsoft.EntityFrameworkCore.Tools]
  • 點選 [安裝] 按鈕以便安裝這個套件

使用反向工程來產生 Entity Framework 要用到的 Entity 模型相關類別

  • 切換到 [套件管理器主控台] 視窗

    若沒有看到 [套件管理器主控台] 視窗,點選功能表 [工具] > [NuGet 套件管理員] > [套件管理器主控台]

  • 在 [套件管理器主控台] 輸入底下內容

    因為都在同一個專案內,所以,這裡可以省略 StartupProject & Project 這兩個參數,因此,底下的指令會更為精簡

Scaffold-DbContext "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=School" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -f

請打開這個 [Program.cs] 檔案,完成底下的程式碼

static void Main(string[] args)
{
    using (var context = new SchoolContext())
    {
        Console.WriteLine($"執行任何資料庫存取動作前的 ChangeTracker");
        DisplayStates(context.ChangeTracker.Entries());
        Console.WriteLine($"查詢第一筆 Person 紀錄,但使用 AsNoTracking");
        var person = context.Person.AsNoTracking().FirstOrDefault();
        DisplayStates(context.ChangeTracker.Entries());
        Console.WriteLine($"查詢第一筆 Person 紀錄 ");
        person = context.Person.FirstOrDefault();
        DisplayStates(context.ChangeTracker.Entries());
        Console.WriteLine($"修改與更新 Person 紀錄 ");
        person.LastName = $"{person.LastName}1";
        DisplayStates(context.ChangeTracker.Entries());
    }
}

這裡將要說明 Entity Framework Core 的變更追蹤的使用方式,這裡設計一個方法 [DisplayStates] ,該方法會接收一個 IEnumerable<EntityEntry> 的參數,接著,會將該列舉的 EntityEntry 集合物件內的名稱與狀態,顯示出來,更多這方面的資訊,可以參考 EntityEntry

在主程式那哩,首先會先呼叫 [DisplayStates] 方法,確認 Entity Framework Core 的變更追蹤內沒有任何的紀錄存在,接著會取得 Person 這個資料表內的第一筆紀錄出來,不過,這裡會呼叫 AsNoTracking() 無追蹤查詢 方法,指定此次資料查詢動作,不需要做異動追蹤;因此,可以得知,當執行完成之後,Entity Framework Core 的變更追蹤是沒有任何資料存在的

private static void DisplayStates(IEnumerable<EntityEntry> entries)
{
    foreach (var entry in entries)
    {
        Console.WriteLine($"Entity: {entry.Entity.GetType().Name}," +
            $"State: { entry.State.ToString()}");
    }
}

接著同樣的再度呼叫 context.Person.FirstOrDefault() 方法,查詢出 Person 資料庫內的第一筆紀錄,不過,這次將會採用預設的 Entity Framework Core 的變更追蹤功能,因此,當這個敘述執行完成之後,Entity Framework Core 的變更追蹤內將會有一筆紀錄存在。這筆紀錄的狀態值將會是 ntity: Person,State: Unchanged

最後,嘗試將剛剛查詢出來的人員物件的 LastName 屬性作變更,並且再度呼叫 [DisplayStates] 方法,將會看到這樣的輸出內容: Entity: Person,State: Modified 代表該紀錄已經被修改過了,也就是說,當呼叫 SaveChanges 方法之後,Entity Framework Core 將會產生一筆 Update 的 SQL 敘述到資料庫內,以便更新該筆紀錄。

底下是執行結果


執行任何資料庫存取動作前的 ChangeTracker
查詢第一筆 Person 紀錄,但使用 AsNoTracking
查詢第一筆 Person 紀錄
Entity: Person,State: Unchanged
修改與更新 Person 紀錄
Entity: Person,State: Modified







2020年10月22日 星期四

Entity Framework Core EF Core 的 紀錄刪除

Entity Framework Core EF Core 的 紀錄刪除

在上一篇 EF Core 討論文章 EF Core 的 紀錄修改 ,說明了如何使用 EF Core 來修改資料庫紀錄的做法。

在這篇文章中,來了解如何使用 EF Core 來進行記錄刪除動作的作法,關於更多這方面的應用,可以參考 基本儲存 這份文件內容。

請按照底下的步驟來進行操作

建立練習專案

  • 打開 Visual Studio 2019

  • 點選 [建立新的專案] 按鈕

  • 在 [建立新專案] 對話窗內,選擇 [Blazor 應用程式] 專案樣板

  • 在 [設定新的專案] 對話窗內,於 [專案名稱] 欄位內輸入 efDeleteRecord

  • 在 [建立新的 Blazor 應用程式] 對話窗內,選擇 [Blazor 伺服器應用程式] 這個選項

    在該對話窗右半部的其他選項,可以不用變更

  • 點選 [建立] 按鈕,以便開始建立這個專案

加入 Entity Framework Core 要使用到的 NuGet 套件

  • 滑鼠右擊專案內的 [相依性] 節點
  • 選擇 [管理 NuGet 套件]
  • 點選 [瀏覽] 標籤分頁頁次
  • 在 [搜尋] 文字輸入盒內,輸入 [Microsoft.EntityFrameworkCore.SqlServer]
  • 點選 [安裝] 按鈕以便安裝這個套件
  • 在 [搜尋] 文字輸入盒內,輸入 [Microsoft.EntityFrameworkCore.Tools]
  • 點選 [安裝] 按鈕以便安裝這個套件

使用反向工程來產生 Entity Framework 要用到的 Entity 模型相關類別

  • 切換到 [套件管理器主控台] 視窗

    若沒有看到 [套件管理器主控台] 視窗,點選功能表 [工具] > [NuGet 套件管理員] > [套件管理器主控台]

  • 在 [套件管理器主控台] 輸入底下內容

    因為都在同一個專案內,所以,這裡可以省略 StartupProject & Project 這兩個參數,因此,底下的指令會更為精簡

Scaffold-DbContext "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=School" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -f

請打開這個 [Program.cs] 檔案,完成底下的程式碼

static void Main(string[] args)
{
    var context = new DataContext();
    context.Database.EnsureDeleted();
    context.Database.EnsureCreated();
 
    context.Department.Add(new Department());
    context.Entry(new Department()).State = EntityState.Added;
    context.SaveChanges();
    Console.WriteLine($"科系記錄數量:{context.Department.ToList().Count}");
    var departments = context.Department.ToList();
    Reset(context); // 清除 ChangeTracker 內的科系紀錄
    context.Department.Remove(departments[0]);
    context.Entry(departments[1]).State = EntityState.Deleted;
    context.SaveChanges();
    Console.WriteLine($"科系記錄數量:{context.Department.ToList().Count}");
}
public static void Reset(DataContext context)
{
    #region 解除快取紀錄
    foreach (var item in context
        .Set<Department>().Local.ToList())
    {
        context.Entry(item).State = 
            Microsoft.EntityFrameworkCore.EntityState.Detached;
    }
    #endregion
}

上面的程式碼使用 new 運算子來建立兩個 Department 類別的物件,分別呼叫了 context.Department.Add(new Department()); 與 context.Entry(new Department()).State = EntityState.Added; 這兩個敘述,並且呼叫了 SaveChanges 告知 Entity Framework Core 將這筆紀錄新增到資料庫,接著使用了 context.Department.ToList().Count 敘述,顯示出 科系 Department 資料表內究竟有多少筆記錄存在,不用猜想,這裡當然會顯示出僅有2筆紀錄存在。

現在使用了 var departments = context.Department.ToList() 敘述,將科系資料表內的所有紀錄都取回到 .NET 環境內,並且這些紀錄都會在 Entity Framework Core 的變更追蹤系統內有份紀錄,而這裡也會呼叫一個客製方法 Reset(context),這個方法將會清除 ChangeTracker 內的有關科系紀錄,這樣在 Entity Framework Core 內的變更追蹤系統內,就都沒有任何有關科系資料表相關的最新紀錄了。

使用這個敘述 context.Department.Remove(departments[0]) 將第一筆科系紀錄刪除掉,而使用這個敘述 context.Entry(departments[1]).State = EntityState.Deleted 將第二個科系紀錄也刪除掉,這兩種作法都是得到相同的結果。

最後呼叫 context.SaveChanges() 來通知 EF Core 產生 Delete 的 SQL 敘述,讓資料庫刪除這兩筆紀錄,而最後的 Console.WriteLine($"科系記錄數量:{context.Department.ToList().Count}") 敘述,將會得到沒有任何紀錄的輸出結果。

底下是執行結果

科系記錄數量:2
科系記錄數量:0

 



2020年10月21日 星期三

Entity Framework Core EF Core 的 紀錄修改

 

Entity Framework Core EF Core 的 紀錄修改

在上一篇 EF Core 討論文章 EF Core 的 紀錄新增 ,說明了如何使用 EF Core 來建立產生一筆新的資料庫紀錄的做法。

在這篇文章中,來了解如何使用 EF Core 來進行記錄修改動作的作法,關於更多這方面的應用,可以參考 基本儲存 這份文件內容。

請按照底下的步驟來進行操作

建立練習專案

  • 打開 Visual Studio 2019

  • 點選 [建立新的專案] 按鈕

  • 在 [建立新專案] 對話窗內,選擇 [Blazor 應用程式] 專案樣板

  • 在 [設定新的專案] 對話窗內,於 [專案名稱] 欄位內輸入 efUpdateRecord

  • 在 [建立新的 Blazor 應用程式] 對話窗內,選擇 [Blazor 伺服器應用程式] 這個選項

    在該對話窗右半部的其他選項,可以不用變更

  • 點選 [建立] 按鈕,以便開始建立這個專案

加入 Entity Framework Core 要使用到的 NuGet 套件

  • 滑鼠右擊專案內的 [相依性] 節點
  • 選擇 [管理 NuGet 套件]
  • 點選 [瀏覽] 標籤分頁頁次
  • 在 [搜尋] 文字輸入盒內,輸入 [Microsoft.EntityFrameworkCore.SqlServer]
  • 點選 [安裝] 按鈕以便安裝這個套件
  • 在 [搜尋] 文字輸入盒內,輸入 [Microsoft.EntityFrameworkCore.Tools]
  • 點選 [安裝] 按鈕以便安裝這個套件

使用反向工程來產生 Entity Framework 要用到的 Entity 模型相關類別

  • 切換到 [套件管理器主控台] 視窗

    若沒有看到 [套件管理器主控台] 視窗,點選功能表 [工具] > [NuGet 套件管理員] > [套件管理器主控台]

  • 在 [套件管理器主控台] 輸入底下內容

    因為都在同一個專案內,所以,這裡可以省略 StartupProject & Project 這兩個參數,因此,底下的指令會更為精簡

Scaffold-DbContext "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=School" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -f

請打開這個 [Program.cs] 檔案,完成底下的程式碼

var context = new DataContext();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
 
Department department1 = new Department() { Name = "新增的科系1", };
context.Department.Add(department1);
context.SaveChanges();
Department department2 = context.Department.First();
department2.Name = "修改該科系名稱";
context.SaveChanges();
Reset(context); // 清除 ChangeTracker 內的科系紀錄
Department department3 = new Department()
{
    Id = department1.Id,
    Name = "使用狀態來修改的科系名稱",
};
context.Entry(department3).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
context.SaveChanges();
foreach (var item in context.Department.ToList())
{
    Console.WriteLine($"科系名稱:{item.Name}");
}

public static void Reset(DataContext context)
{
    #region 解除快取紀錄
    foreach (var item in context
        .Set<Department>().Local.ToList())
    {
        context.Entry(item).State = 
            Microsoft.EntityFrameworkCore.EntityState.Detached;
    }
    #endregion
}

上面的程式碼使用 new 運算子來建立 Department 類別的物件,也就是科系名稱為 [新增的科系1] 的紀錄,並且呼叫了 SaveChanges 告知 Entity Framework Core 將這筆紀錄新增到資料庫,不過,記得要呼叫 context.SaveChanges() 方法,這樣的異動請求才會更新到資料庫內;接著,使用了 context.Department.First() 表示式,取得科系資料表內的第一筆紀錄,也就是剛剛建立的紀錄。

現在要來變更剛剛取得的紀錄,也就是 department2 這個物件,使用這樣的敘述 department2.Name = "修改該科系名稱"; ,當想要同步這個 .NET 物件與資料庫內的紀錄時候,還是一樣要使用 呼叫 context.SaveChanges() 方法,因為 Entity Framework Core 發現到在變更追蹤內的紀錄,與剛剛修改的物件不相同,因此,將會產生出 Update 的 SQL 敘述,並且把這個敘述送到資料庫內。

由於在取得科系資料表內的第一筆紀錄的時候,使用了 Department department2 = context.Department.First(); 這樣的敘述,因此,在 Entity Framework Core 內的變更追蹤內,將會有剛剛取得的紀錄物件,現在將會呼叫一個客製方法 Reset(context),這個方法將會清除 ChangeTracker 內的有關科系紀錄,這樣在 Entity Framework Core 內的變更追蹤系統內,就都沒有任何有關科系資料表相關的最新紀錄了。

在這裡使用 C# new 運算子,建立一個 department3 的物件

接下來,將使用 C# new 運算子,建立一個 department3 .NET 物件,不過,該物件的 Id 屬性值將會與 department1的物件值相同,不過科系名稱欄位卻是不同的內容,由於由於 Entity Framework Core 內的變更追蹤系統內,沒有任何有關科系資料表相關的最新紀錄,因此,當下達 context.SaveChanges() 方法,這個物件的異動,是不會同步到資料庫內,因此,需要使用下面兩種做法的其中一個。

第一個做法是下達 context.Department.Update(department3); 這樣的敘述,如同前一篇文章要新增一筆紀錄相同,只不過這裡要呼叫的 Update 這樣的方法;第二種做法是使用 context.Entry(department3).State = Microsoft.EntityFrameworkCore.EntityState.Modified; 這樣的敘述,通知 Entity Framework Core 的變更追蹤系統,有一筆紀錄要更新到資料庫內。

不論是哪種做法,最後都要 呼叫 context.SaveChanges() 方法

上面的程式會再度查詢資料庫內所有科系的紀錄,並且顯示在螢幕上,底下是執行結果

科系名稱:使用狀態來修改的科系名稱




2020年10月20日 星期二

Entity Framework Core EF Core 的 紀錄新增

Entity Framework Core EF Core 的 紀錄新增

在上一篇 EF Core 討論文章 Entity Framework Core 一對多的資料讀取 ,說明了如何使用 EF Core 來取得導航屬性內的關聯紀錄做法。

在這篇文章中,來了解如何使用 EF Core 來進行記錄新增動作的作法,關於更多這方面的應用,可以參考 基本儲存 這份文件內容。

請按照底下的步驟來進行操作

建立練習專案

  • 打開 Visual Studio 2019

  • 點選 [建立新的專案] 按鈕

  • 在 [建立新專案] 對話窗內,選擇 [Blazor 應用程式] 專案樣板

  • 在 [設定新的專案] 對話窗內,於 [專案名稱] 欄位內輸入 efAddRecord

  • 在 [建立新的 Blazor 應用程式] 對話窗內,選擇 [Blazor 伺服器應用程式] 這個選項

    在該對話窗右半部的其他選項,可以不用變更

  • 點選 [建立] 按鈕,以便開始建立這個專案

加入 Entity Framework Core 要使用到的 NuGet 套件

  • 滑鼠右擊專案內的 [相依性] 節點
  • 選擇 [管理 NuGet 套件]
  • 點選 [瀏覽] 標籤分頁頁次
  • 在 [搜尋] 文字輸入盒內,輸入 [Microsoft.EntityFrameworkCore.SqlServer]
  • 點選 [安裝] 按鈕以便安裝這個套件
  • 在 [搜尋] 文字輸入盒內,輸入 [Microsoft.EntityFrameworkCore.Tools]
  • 點選 [安裝] 按鈕以便安裝這個套件

使用反向工程來產生 Entity Framework 要用到的 Entity 模型相關類別

  • 切換到 [套件管理器主控台] 視窗

    若沒有看到 [套件管理器主控台] 視窗,點選功能表 [工具] > [NuGet 套件管理員] > [套件管理器主控台]

  • 在 [套件管理器主控台] 輸入底下內容

    因為都在同一個專案內,所以,這裡可以省略 StartupProject & Project 這兩個參數,因此,底下的指令會更為精簡

Scaffold-DbContext "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=School" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -f

請打開這個 [Program.cs] 檔案,完成底下的程式碼

var context = new DataContext();
Department department1 = new Department()
{
    Name = "新增的科系1",
};
context.Department.Add(department1);
context.SaveChanges();
Department department2 = new Department()
{
    Name = "新增的科系2",
};
context.Entry(department2).State = Microsoft.EntityFrameworkCore.EntityState.Added;
context.SaveChanges();
foreach (var item in context.Department.ToList())
{
    Console.WriteLine($"科系名稱:{item.Name}");
}

上面的程式碼說明了兩種新增記錄到後端資料庫內的作法,其實這兩種作法都是相同的,不論是哪一種做法,首先需要建立一個 Entity 類別的執行個體,這裡是要新增兩筆科系的紀錄,因此,需要使用 new 運算子來建立 Department 類別的物件。

一旦 Entity 的物件產生完成之後,便可以使用這樣的作法 context.Department.Add(department1) 將剛剛建立的物件,通知 EF Core 要準備把這個物件新增到資料庫內,最後,呼叫 context.SaveChanges(); 便會把 Entity Framework Core 內的變更追蹤的紀錄比對一次,便會發現到有要新增一筆紀錄的請求,接著便會產生 Insert SQL 敘述,把這個物件新增到資料庫內,成為一筆新的紀錄。

第二種作法那就是使用 context.Entry(department2).State = Microsoft.EntityFrameworkCore.EntityState.Added; 這樣的作法,宣告這個物件需要在下次呼叫 SaveChanges 的時候,將這個物件新增到資料庫內。

上面的程式會再度查詢資料庫內所有科系的紀錄,並且顯示在螢幕上,底下是執行結果

科系名稱:新增的科系1 

科系名稱:新增的科系2