在用Entity Framework(簡稱EF)時,會常常使用到LINQ語法來對DB資料進行CRUD操作。然而LINQ語法畢竟不是標準的SQL語法,所以每次Debug遇到執行的結果與預期不同時,因為不知道轉出來的SQL是怎樣,所以通常都不知道如何下手。但是不用擔心,因為EF有提供LINQ語法所轉出來的SQL字串LOG,讓開發者可以輕鬆Debug,現在就來看看如何取得轉換出來的SQL字串吧。
在講方法前先來說說EF6與之前版本的差異。在EF之前的版本,建置一個DB連線需要寫一堆Code,譬如ObjectContext的每個ObjectSet屬性都要複寫get方法呼叫CreateObjectSet<T>(""),還有其他哩哩叩叩的程式碼要寫,而EF6為了加快開發速度,將ObjectContext包裝成DbContext,ObjectSet包裝成DbSet,少寫了1/3左右的程式。再來進入重點,EF6的DbContext中有個Database屬性,Database屬性其實就像是一般ADO.NET中管理DB連線相關功能的集合體,例如DbConnection, DbCommand...等,可以用Database屬性提供的方法來進行SQL的CRUD。EF6在Database中加入一個Log屬性,Log屬性其實就是本篇要介紹的取得LINQ轉換出的SQL字串方法,下面來看看MSDN上說明Database.Log的屬性是什麼東東:
從MSDN說明看來,可以知道EF在執行的時候會產生LOG,這些LOG如果沒有指定處理方式的話就不會顯示出來,因此才有了Log這個屬性。Log屬性為Action<string>的Type,就是EF回傳入String型態的資料到你所指定的Function裡進行處理。以下限量會以兩種情境來使用EF的Log。第一種為在Console App中將EF轉換出的SQL字串印出來;第二種為在VS Debug時看EF轉換出的SQL字串。在範例中,先進行DELETE動作將資料表清空,再來新增一筆資料,最後將資料表內所有資料撈出,這三個動作會有三個SQL,下面就來看看範例產生的SQL長得如何。
範例程式碼:
執行結果:
將Database.Log修改成以下:
執行結果:
這樣就能輕輕鬆鬆的在Debug階段Trace用LINQ下的SQL語法是否正確了。取到了SQL字串後就可以用在其他應用上,像是寫出成檔案或丟給Log模組寫Log...等。
參考來源:
One Unicorn - EF6 SQL Logging – Part 1: Simple Logging
在講方法前先來說說EF6與之前版本的差異。在EF之前的版本,建置一個DB連線需要寫一堆Code,譬如ObjectContext的每個ObjectSet屬性都要複寫get方法呼叫CreateObjectSet<T>(""),還有其他哩哩叩叩的程式碼要寫,而EF6為了加快開發速度,將ObjectContext包裝成DbContext,ObjectSet包裝成DbSet,少寫了1/3左右的程式。再來進入重點,EF6的DbContext中有個Database屬性,Database屬性其實就像是一般ADO.NET中管理DB連線相關功能的集合體,例如DbConnection, DbCommand...等,可以用Database屬性提供的方法來進行SQL的CRUD。EF6在Database中加入一個Log屬性,Log屬性其實就是本篇要介紹的取得LINQ轉換出的SQL字串方法,下面來看看MSDN上說明Database.Log的屬性是什麼東東:
從MSDN說明看來,可以知道EF在執行的時候會產生LOG,這些LOG如果沒有指定處理方式的話就不會顯示出來,因此才有了Log這個屬性。Log屬性為Action<string>的Type,就是EF回傳入String型態的資料到你所指定的Function裡進行處理。以下限量會以兩種情境來使用EF的Log。第一種為在Console App中將EF轉換出的SQL字串印出來;第二種為在VS Debug時看EF轉換出的SQL字串。在範例中,先進行DELETE動作將資料表清空,再來新增一筆資料,最後將資料表內所有資料撈出,這三個動作會有三個SQL,下面就來看看範例產生的SQL長得如何。
情境一(Console印出)
範例程式碼:
class Program { static void Main( string[] args ) { using (var db = new PTMContext()) { // 將Log用Console.Write寫出 db.Database.Log = Console.Write; // 刪除所有USERINFO TABLE資料 db.Database.ExecuteSqlCommand("DELETE FROM USERINFO"); // 新增一筆USERINFO var user = new UserInfo { Id = Guid.NewGuid(), Account = "Admin", Name = "Limited", Nickname = "Administrator", Password = "admin123", Email = "Test@Test.com", PhoneNum = "0912345678", AddDate = DateTime.Now, AddUserId = "Test", ModDate = DateTime.Now, ModUserId = "Test" }; db.Users.Add(user); // Commit db.SaveChanges(); // 取得所有USERINFO TABLE資料 var users = db.Users.ToList(); // 印出TABLE資料 PrintTable<UserInfo>(users); } Console.ReadLine(); } /// <summary> /// Console印出Table資料 /// </summary> /// <typeparam name="T">Table Mapping Model</typeparam> /// <param name="list">Records</param> static void PrintTable<T>(IEnumerable<T> list) where T : class { var type = typeof(T); var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); var colNames = props.Select(x => x.Name); var headerStr = string.Join(" | ", colNames); Console.WriteLine(type.Name); Console.WriteLine(headerStr); for (var i = 0; i < headerStr.Length; i++) { Console.Write("-"); } Console.WriteLine(); foreach (var row in list) { var rowStr = string.Empty; foreach (var prop in props) { var propVal = prop.GetValue(row); rowStr = string.Join(" | ", rowStr, propVal == null ? string.Empty : propVal.ToString()); } Console.WriteLine(rowStr); for (var i = 0; i < rowStr.Length; i++) { Console.Write("-"); } Console.Write("\n\n\n"); } } }
執行結果:
情境二(在VS的輸出視窗中顯示)
將Database.Log修改成以下:
db.Database.Log = log => System.Diagnostics.Debug.Write(log);
執行結果:
這樣就能輕輕鬆鬆的在Debug階段Trace用LINQ下的SQL語法是否正確了。取到了SQL字串後就可以用在其他應用上,像是寫出成檔案或丟給Log模組寫Log...等。
參考來源:
One Unicorn - EF6 SQL Logging – Part 1: Simple Logging
留言
張貼留言