Entity Framework入門教程(13)---EF中的高併發

EF中的高併發

  這裏只介紹EF6中database-first開發方案的高併發解決方案,code-first開發方案中的高併發會在之後的EF CodeFirst系列中介紹。html

  EF默認支持樂觀併發:咱們從數據庫加載了一條數據,這是有人修改了這條數據,而咱們手中用的仍是舊數據,這就出現了髒讀,這個時候咱們修改了這條數據而後執行SaveChange()會發生什麼呢?EF在保存數據時會首先查看數據庫中的數據有沒有改變過,數據沒有改變就執行保存;數據改變了會拋出異常,咱們再次提交前必須解決衝突(提到解決衝突是否是想到了git提交中的衝突?EF中解決高併發的方法和git提交的方法採用的思想是同樣的,往下看就知道了)。git

1.使用步驟

1.添加RowVersion列數據庫

  在EF中database-first開發模式中,爲了解決高併發問題咱們能夠爲數據表填加一個timestamp類型的的列,列名爲rowversion,rowversion是一個二進制的數據,在每次的添加/修改操做後rowversion的值都會變大併發

以Student實體爲例,給Student表添加一個Rowversion列,類型爲timestamp,以下所示:高併發

2.生成/升級EMDpost

若是沒有EDM經過數據庫生成新的實體數據模型,若是有EDM則右擊設計器->Update Model From Database ->Refresh Student table,這時咱們就能夠在設計器中看到RowVersion屬性了,RowVersion屬性的Concurrency Mode設置爲Fixed,以下圖spa

作完這兩步,EF API在執行Update時,會把RowVersion添加到where子句中(就像這樣:update tb set cloName=xxx where Id=@id and RowVersion=@rowversion),若是where子句中的RowVersion值和數據庫中的不同就拋出DbUpdateConcurrencyException設計

2.一個栗子

Student student = null; 

using (var context = new SchoolDBEntities())
{
    student = context.Students.First();
}

//修改學生名字
Console.Write("Enter New Student Name:");
student.StudentName = Console.ReadLine(); //Assigns student name from console

using (var context = new SchoolDBEntities())
{
    try
    {
        context.Entry(student).State = EntityState.Modified;
        context.SaveChanges();

        Console.WriteLine("修改爲功!");
    }
    catch (DbUpdateConcurrencyException ex)
    {
        Console.WriteLine("發生高併發異常!");
    }
}

假設有兩個用戶都在執行上邊的代碼,User1和User2拿到了同一個Student實例,User1打字快1秒就把這個Student的用戶修改了,並在數據庫保存成功(User1執行Update時RowVersion和數據庫一致,因此不報錯,保存完成後Student的RowVersion自動改變了),這時User2也完成了修改,在User2執行保存到數據庫時(生成的Update語句中的RowVersion和數據庫中不一致了,因此拋出異常)。code

 

EF系列目錄連接:Entity Franmework系列教程彙總htm

相關文章
相關標籤/搜索