在用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



留言
張貼留言