1. 程式人生 > >EF6學習筆記二十四:事務

EF6學習筆記二十四:事務

lba security laptop date 簡單的 nbsp sed als 詳細

要專業系統地學習EF推薦《你必須掌握的Entity Framework 6.x與Core 2.0》。這本書作者(汪鵬,Jeffcky)的博客:https://www.cnblogs.com/CreateMyself/

了解一下EF中事務。首先復習一下原始的SQL語句創建事務,然後也復習一下ADO中事務的使用。工作一年多我就沒寫過事務,因為用的是EF,事務就只是在學校中寫過。

詳細學習事務:https://www.cnblogs.com/knowledgesea/p/3714417.html

技術分享圖片
begin transaction
begin try
     insert into tb_Students values
(newid(),小明,44,2012-1-1); insert into tb_Teachers values(newid(),張四海,語文,2018-2-2); end try begin catch select ERROR_NUMBER() as ErrorNumber, -- 錯誤代碼 ERROR_SEVERITY() as ErrorSeverity,-- 錯誤嚴重級別,級別小於10,try catch捕獲不到 ERROR_STATE() as ErrorState, -- 錯誤狀態碼
ERROR_PROCEDURE() as ErrorProcedure, -- 出現錯誤的存儲過程或觸發器的名稱 ERROR_LINE() as ErrorLine, -- 發生錯誤的行號 ERROR_MESSAGE() as ErrorMessage -- 錯誤的具體信息 if(@@TRANCOUNT > 0) -- 事務開啟此值+1,判斷是否開啟事務 rollback transaction end catch if(@@TRANCOUNT >
0) commit tran
View Code 技術分享圖片
//  ado中使用事務
string connStr = @"Data Source=LAPTOP-G81QJ856\SQLEXPRESS;Initial Catalog=_20190130.EFDbContext;Integrated Security=True";
using (SqlConnection conn = new SqlConnection(connStr))
{
    Console.WriteLine(conn.State);  //  closed  我還以為使用using自動打開的
    conn.Open();
    string sql = @"insert into tb_Students values(newid(),‘小強‘,‘44‘,‘2012-1-1‘);insert into tb_Teachers values(newid(),‘張拋‘,‘數學‘,‘1999-9-2‘);";
    using (SqlCommand cmd = new SqlCommand(sql, conn))
    {
        using (SqlTransaction tran = conn.BeginTransaction())
        {
            try
            {
                //  如果不告訴cmd使用哪個事務會報錯
                ////  System.InvalidOperationException: 如果分配給命令的連接位於本地掛起事務中,ExecuteNonQuery 要求命令擁有 事務。命令的 Transaction 屬性尚未初始化。
                cmd.Transaction = tran; 
                var i = cmd.ExecuteNonQuery();
                tran.Commit();
            }
            catch (Exception e)
            {
                tran.Rollback();
                throw e;  
            }
        }
    }
}
View Code

現在來看看EF中事務是怎麽回事

我們平時在執行添加、修改、刪除調用SaveChanges方法時,就會被默認的被事務包裹。查詢沒有

技術分享圖片
ctx.Students.Add(new Student { Name = "小劉", Score = "55", AddTime = DateTime.Now });
View Code

技術分享圖片

當我們多次調用SaveChanges時,就會開啟多個事務。

技術分享圖片
ctx.Students.Add(new Student { Name="小新",Score="66"});
ctx.SaveChanges();
ctx.Teachers.Add(new Teacher { Name="胡飄",Subject="歷史"});
ctx.SaveChanges();
View Code

技術分享圖片

現在來看EF中的一個關於事務的配置

技術分享圖片
public class EFDbContext : DbContext
    {
        public EFDbContext()
        {
            //此標誌確定在使用此類方法時是否啟動新事務
            Configuration.EnsureTransactionsForFunctionsAndCommands = false;
        }
}
View Code

這個就是開啟關閉事務的開關,但是他對SaveChanges是不起作用的,目前我只知道調用ExecuteSqlCommand方式時才有用。MSDN上對這個都說的很簡陋

技術分享圖片

那麽看看EF中對這個屬性的註釋

技術分享圖片

還是直接來看看,下面這條語句我關閉事務, 添加一條記錄,然後調用SaveChanges,但其實,還是會開啟事務

技術分享圖片
  //  還是會有事務的            ctx.Configuration.EnsureTransactionsForFunctionsAndCommands = false;
ctx.Database.Log = msg => Console.WriteLine(msg);
ctx.Teachers.Add(new Teacher { Name = "胡憤", Subject = "歷史" });
ctx.Students.Add(new Student { Name = "小趙", Score = "66", AddTime = DateTime.MinValue });
ctx.SaveChanges();
View Code

ExecuteSqlCommand也是默認被事務包裹,但是他就可以通過傳遞參數來實現事務的開啟和關閉。

技術分享圖片
ctx.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, @"insert into tb_students values(newid(),‘小劉‘,‘70‘,getdate())");
View Code

行吧,就是這樣。

如果說我們想用ADO中那種方式來使用事務呢?當然是可以的,上下文提供了BeginTransaction,和ADO中的命名是一樣的。

技術分享圖片
using (var transaction = ctx.Database.BeginTransaction())
{
    ctx.Teachers.Add(new Teacher { Name = "胡憤", Subject = "歷史" });
    ctx.SaveChanges();
    ctx.Students.Add(new Student { Name = "小趙", Score = "66", AddTime = DateTime.Now });
    ctx.SaveChanges();
    transaction.Commit();
}
View Code

我雖然調用了兩次saveChanges,但只有一個事務,但是必須要調用一次SaveChanges才能成功插入

技術分享圖片

最後開看一下EF提供的UseTransaction方法,這個是什麽意思呢?允許上下文參與到已存在的事務中。

我們現在使用ADO,將ADO的transaction對象傳遞給EF的UseTransaction,那麽我在ADO中的操作和在EF中的操作就可以處在同一個事務中

技術分享圖片
string connStr = @"Data Source=LAPTOP-G81QJ856\SQLEXPRESS;Initial Catalog=_20190130.EFDbContext;Integrated Security=True";
using (SqlConnection conn = new SqlConnection(connStr))
{
    conn.Open();
    string sql = @"insert into tb_students values(newid(),‘小藍 ‘,‘70‘,getdate())";
    using (SqlCommand cmd = new SqlCommand(sql, conn))
    {
        using (SqlTransaction tran = conn.BeginTransaction())
        {
            try
            {
                cmd.Transaction = tran;
                var i = cmd.ExecuteNonQuery();
                using (EFDbContext ctx = new EFDbContext(conn))
                {
                    ctx.Database.UseTransaction(tran);
                    ctx.Students.Add(new Student { Name = "小紅", Score = "55", AddTime = DateTime.Now });
                    ctx.SaveChanges();
                }
                tran.Commit();
            }
            catch (Exception e)
            {
                tran.Rollback();
                throw e;
            }
        }
    }
}
View Code

行吧,EF中簡單的事務就到這裏了。

EF6學習筆記二十四:事務