EntityFramework監控sql和EntityFramework中的事務


繼續上篇:EntityFramework和EntityFramework.Extended使用說明——性能,語法和產生的sql

1.監控sql

上篇中的sql監控采用的是 Microsoft SQL Server Management Studio中工具->profiler去監控的.
當然,Express版本是沒有此功能的.
如果您使用不了profiler或者覺得不方便,那么,給出監控sql的第二方案.

找到的資料是英文的,還好,容易理解.
原文鏈接:https://blog.oneunicorn.com/2013/05/08/ef6-sql-logging-part-1-simple-logging/

a.控制台打印

var db = new PhoneBookEntities();//以后的db都是指它
db.Database.Log = Console.Write;//打印sql語句
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=220");//此語句不用db.SaveChanges();一樣生效

監控結果:

已於 2016/6/21 星期二 10:30:23 +08:00
 打開了連接已於 2016/6/21 星期二 10:30:23 +08:00
 啟動了事務update GroupInfo set GroupName='hi' where GroupId=220
-- 正在 2016/6/21 星期二 10:30:23 +08:00
 執行-- 已在 1 毫秒內完成,結果為: 1

已於 2016/6/21 星期二 10:30:23 +08:00
 提交了事務已於 2016/6/21 星期二 10:30:23 +08:00
 關閉了連接

b.記錄sql到文件

如果控制台打印不能滿足您的需求,也可以記錄到文件里.
方法:

 var db = new PhoneBookEntities();
 db.Database.Log = s => LogHelper.Write(s);//調用LogHelper類的方法
 db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=220");//此語句不用db.SaveChanges();一樣生效

LogHelper.cs

    public class LogHelper
    {
        public static void Write(string str)
        {
            var path = Path.Combine(new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).Parent.Parent.FullName, "logs.txt");
            string errmsg = string.Format("{0}", str);
            System.IO.File.AppendAllText(path, errmsg);
        }
    }

就是這么簡單!

2.EF中的事務

上面例子看到產生的sql監控記錄,
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=220");
此語句執行啟動了事務.

測試研究一下怎么回事.
以下兩句:
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hi' where GroupId=209");
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=220");
經監控,分別啟動並提交了兩次事務.(如果sql命令為insert,delete也是同樣道理)

怎么把這兩個sql語句放到一個事務里呢?別急,最后再說明.

先看看最熟悉的db.SaveChanges()語句:以下語句本身沒有實際意義,為了測試而寫.

var gi = db.GroupInfo.FirstOrDefault(c => c.GroupName.Contains("g1!"));
var ci = db.ContactInfo.FirstOrDefault(c => c.ID == 12);
ci.ContactName += "!";
gi.GroupName += "!";
db.SaveChanges();
ci.ContactName += "!";
gi.GroupName += "!";
db.SaveChanges();

監控產生的sql:

已於 2016/6/21 星期二 11:06:52 +08:00
 打開了連接SELECT TOP (1) 
    [Extent1].[GroupId] AS [GroupId], 
    [Extent1].[GroupName] AS [GroupName]
    FROM [dbo].[GroupInfo] AS [Extent1]
    WHERE [Extent1].[GroupName] LIKE N'%g1!%'
-- 正在 2016/6/21 星期二 11:06:52 +08:00
 執行-- 已在 1 毫秒內完成,結果為: SqlDataReader

已於 2016/6/21 星期二 11:06:52 +08:00
 關閉了連接已於 2016/6/21 星期二 11:06:52 +08:00
 打開了連接SELECT TOP (1) 
    [Extent1].[ID] AS [ID], 
    [Extent1].[ContactId] AS [ContactId], 
    [Extent1].[IsDelete] AS [IsDelete], 
    [Extent1].[Account] AS [Account], 
    [Extent1].[ContactName] AS [ContactName], 
    [Extent1].[CommonMobile] AS [CommonMobile], 
    [Extent1].[HeadPortrait] AS [HeadPortrait], 
    [Extent1].[AttFile] AS [AttFile], 
    [Extent1].[GroupId] AS [GroupId]
    FROM [dbo].[ContactInfo] AS [Extent1]
    WHERE 12 = [Extent1].[ID]
-- 正在 2016/6/21 星期二 11:06:52 +08:00
 執行-- 已在 1 毫秒內完成,結果為: SqlDataReader

已於 2016/6/21 星期二 11:06:52 +08:00
 關閉了連接已於 2016/6/21 星期二 11:06:52 +08:00
 打開了連接已於 2016/6/21 星期二 11:06:52 +08:00
 啟動了事務UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!!!!!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:06:52 +08:00
 執行-- 已在 1 毫秒內完成,結果為: 1

UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' (Type = String, Size = 300)
-- @1: '216' (Type = Int32)
-- 正在 2016/6/21 星期二 11:06:52 +08:00
 執行-- 已在 0 毫秒內完成,結果為: 1

已於 2016/6/21 星期二 11:06:52 +08:00
 提交了事務已於 2016/6/21 星期二 11:06:52 +08:00
 關閉了連接已於 2016/6/21 星期二 11:06:52 +08:00
 打開了連接已於 2016/6/21 星期二 11:06:52 +08:00
 啟動了事務UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!!!!!!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:06:52 +08:00
 執行-- 已在 0 毫秒內完成,結果為: 1

UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' (Type = String, Size = 300)
-- @1: '216' (Type = Int32)
-- 正在 2016/6/21 星期二 11:06:52 +08:00
 執行-- 已在 0 毫秒內完成,結果為: 1

已於 2016/6/21 星期二 11:06:52 +08:00
 提交了事務已於 2016/6/21 星期二 11:06:52 +08:00
 關閉了連接
監控記錄

每次db.SaveChanges()會默認開啟事務,執行sql語句,提交事務.多看看,好好理解一下.

 

如何把兩個db.SaveChanges()放到一個事務里呢?

寫法:

    var gi = db.GroupInfo.FirstOrDefault(c => c.GroupName.Contains("g1!"));
    var ci = db.ContactInfo.FirstOrDefault(c => c.ID == 12);
    using (var tx = db.Database.BeginTransaction())
    {
    try
    {
        ci.ContactName += "!";
        gi.GroupName += "!";
        //db.SaveChanges();//這個語句影響到事務中sql的數量,有此語句事務里4條sql,沒有就是2條.對於此案例,不影響結果.
        ci.ContactName += "!";
        gi.GroupName += "!";
        db.SaveChanges();//必須要有
        tx.Commit();//此語句不要漏了,否則監控結果會是釋放了事務,而不是提交了事務!
    }
    catch (Exception)
    {
        tx.Rollback();
    }
    }

監控產生的sql:

[沒有第一個db.SaveChanges()]

已於 2016/6/21 星期二 11:20:49 +08:00
 打開了連接SELECT TOP (1) 
    [Extent1].[GroupId] AS [GroupId], 
    [Extent1].[GroupName] AS [GroupName]
    FROM [dbo].[GroupInfo] AS [Extent1]
    WHERE [Extent1].[GroupName] LIKE N'%g1!%'
-- 正在 2016/6/21 星期二 11:20:49 +08:00
 執行-- 已在 0 毫秒內完成,結果為: SqlDataReader

已於 2016/6/21 星期二 11:20:49 +08:00
 關閉了連接已於 2016/6/21 星期二 11:20:49 +08:00
 打開了連接SELECT TOP (1) 
    [Extent1].[ID] AS [ID], 
    [Extent1].[ContactId] AS [ContactId], 
    [Extent1].[IsDelete] AS [IsDelete], 
    [Extent1].[Account] AS [Account], 
    [Extent1].[ContactName] AS [ContactName], 
    [Extent1].[CommonMobile] AS [CommonMobile], 
    [Extent1].[HeadPortrait] AS [HeadPortrait], 
    [Extent1].[AttFile] AS [AttFile], 
    [Extent1].[GroupId] AS [GroupId]
    FROM [dbo].[ContactInfo] AS [Extent1]
    WHERE 12 = [Extent1].[ID]
-- 正在 2016/6/21 星期二 11:20:49 +08:00
 執行-- 已在 0 毫秒內完成,結果為: SqlDataReader

已於 2016/6/21 星期二 11:20:49 +08:00
 關閉了連接已於 2016/6/21 星期二 11:20:49 +08:00
 打開了連接已於 2016/6/21 星期二 11:20:49 +08:00
 啟動了事務UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:20:49 +08:00
 執行-- 已在 1 毫秒內完成,結果為: 1

UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!' (Type = String, Size = 300)
-- @1: '222' (Type = Int32)
-- 正在 2016/6/21 星期二 11:20:49 +08:00
 執行-- 已在 0 毫秒內完成,結果為: 1

已於 2016/6/21 星期二 11:20:49 +08:00
 提交了事務已於 2016/6/21 星期二 11:20:49 +08:00
 關閉了連接
監控記錄

[有第一個db.SaveChanges()]

已於 2016/6/21 星期二 11:21:49 +08:00
 打開了連接SELECT TOP (1) 
    [Extent1].[GroupId] AS [GroupId], 
    [Extent1].[GroupName] AS [GroupName]
    FROM [dbo].[GroupInfo] AS [Extent1]
    WHERE [Extent1].[GroupName] LIKE N'%g1!%'
-- 正在 2016/6/21 星期二 11:21:49 +08:00
 執行-- 已在 1 毫秒內完成,結果為: SqlDataReader

已於 2016/6/21 星期二 11:21:49 +08:00
 關閉了連接已於 2016/6/21 星期二 11:21:49 +08:00
 打開了連接SELECT TOP (1) 
    [Extent1].[ID] AS [ID], 
    [Extent1].[ContactId] AS [ContactId], 
    [Extent1].[IsDelete] AS [IsDelete], 
    [Extent1].[Account] AS [Account], 
    [Extent1].[ContactName] AS [ContactName], 
    [Extent1].[CommonMobile] AS [CommonMobile], 
    [Extent1].[HeadPortrait] AS [HeadPortrait], 
    [Extent1].[AttFile] AS [AttFile], 
    [Extent1].[GroupId] AS [GroupId]
    FROM [dbo].[ContactInfo] AS [Extent1]
    WHERE 12 = [Extent1].[ID]
-- 正在 2016/6/21 星期二 11:21:49 +08:00
 執行-- 已在 0 毫秒內完成,結果為: SqlDataReader

已於 2016/6/21 星期二 11:21:49 +08:00
 關閉了連接已於 2016/6/21 星期二 11:21:49 +08:00
 打開了連接已於 2016/6/21 星期二 11:21:49 +08:00
 啟動了事務UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:21:49 +08:00
 執行-- 已在 1 毫秒內完成,結果為: 1

UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!' (Type = String, Size = 300)
-- @1: '222' (Type = Int32)
-- 正在 2016/6/21 星期二 11:21:49 +08:00
 執行-- 已在 1 毫秒內完成,結果為: 1

UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:21:49 +08:00
 執行-- 已在 0 毫秒內完成,結果為: 1

UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!' (Type = String, Size = 300)
-- @1: '222' (Type = Int32)
-- 正在 2016/6/21 星期二 11:21:49 +08:00
 執行-- 已在 0 毫秒內完成,結果為: 1

已於 2016/6/21 星期二 11:21:49 +08:00
 提交了事務已於 2016/6/21 星期二 11:21:49 +08:00
 關閉了連接
監控記錄

解決最初的問題:

    var gi = db.GroupInfo.FirstOrDefault(c => c.GroupName.Contains("g1!"));
    var ci = db.ContactInfo.FirstOrDefault(c => c.ID == 12);
    ci.ContactName += "!";//
    gi.GroupName += "!";  //這兩句放到了using外面,也是可以的
    using (var tx = db.Database.BeginTransaction())
    {
        try
        {
            db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=209");
            db.SaveChanges();//這個語句
            tx.Commit();//此語句不要漏了,否則監控結果會是釋放了事務,而不是提交了事務!
        }
        catch (Exception)
        {
            tx.Rollback();
        }
    }

監控記錄:

已於 2016/6/21 星期二 11:28:28 +08:00
 打開了連接SELECT TOP (1) 
    [Extent1].[GroupId] AS [GroupId], 
    [Extent1].[GroupName] AS [GroupName]
    FROM [dbo].[GroupInfo] AS [Extent1]
    WHERE [Extent1].[GroupName] LIKE N'%g1!%'
-- 正在 2016/6/21 星期二 11:28:28 +08:00
 執行-- 已在 1 毫秒內完成,結果為: SqlDataReader

已於 2016/6/21 星期二 11:28:28 +08:00
 關閉了連接已於 2016/6/21 星期二 11:28:28 +08:00
 打開了連接SELECT TOP (1) 
    [Extent1].[ID] AS [ID], 
    [Extent1].[ContactId] AS [ContactId], 
    [Extent1].[IsDelete] AS [IsDelete], 
    [Extent1].[Account] AS [Account], 
    [Extent1].[ContactName] AS [ContactName], 
    [Extent1].[CommonMobile] AS [CommonMobile], 
    [Extent1].[HeadPortrait] AS [HeadPortrait], 
    [Extent1].[AttFile] AS [AttFile], 
    [Extent1].[GroupId] AS [GroupId]
    FROM [dbo].[ContactInfo] AS [Extent1]
    WHERE 12 = [Extent1].[ID]
-- 正在 2016/6/21 星期二 11:28:28 +08:00
 執行-- 已在 1 毫秒內完成,結果為: SqlDataReader

已於 2016/6/21 星期二 11:28:28 +08:00
 關閉了連接已於 2016/6/21 星期二 11:28:28 +08:00
 打開了連接已於 2016/6/21 星期二 11:28:28 +08:00
 啟動了事務
 update GroupInfo set GroupName='hello' where GroupId=209
-- 正在 2016/6/21 星期二 11:28:28 +08:00
 執行-- 已在 1 毫秒內完成,結果為: 1

UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!!!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:28:28 +08:00
 執行-- 已在 1 毫秒內完成,結果為: 1

UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!!!!' (Type = String, Size = 300)
-- @1: '222' (Type = Int32)
-- 正在 2016/6/21 星期二 11:28:28 +08:00
 執行-- 已在 1 毫秒內完成,結果為: 1

已於 2016/6/21 星期二 11:28:28 +08:00
 提交了事務已於 2016/6/21 星期二 11:28:28 +08:00
 關閉了連接
監控記錄

事務部分,我參考的網址:https://msdn.microsoft.com/zh-cn/magazine/dn532202.aspx

 https://msdn.microsoft.com/en-us/data/dn456843#retry

解釋: Name += "!";這么寫而不是 Name="李四"; 是為了防止EF的自動優化sql.

over...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM