1

我必須在我們的框架中管理併發性,但我無法生成DbUpdateConcurrencyException。我們使用SQL Server 2008,EF 6和AutoMapper 5併發訪問,爲什麼EntityFramework 6不會生成DbUpdateConcurrencyException?

SQL

ALTER TABLE [Keyword].[Keyword] ADD Rowversion [Rowversion] NOT NULL 

型號

[Table("Keyword", Schema = "Mailing")] 
public class KeywordModel : _Auditable 
{ 
    [Key] 
    public int KeywordId { get; set; } 

    public string Name { get; set; } 
    public string Hashtag { get; set; } 
    public string Namespaces { get; set; } 
    public string Html { get; set; } 

    [Timestamp] 
    [ConcurrencyCheck] 
    public virtual byte[] RowVersion { get; set; } 
} 

視圖模型

public class KeywordEditViewModel 
{ 
    [HiddenInput(DisplayValue = false)] 
    public int KeywordId { get; set; } 

    [Display(Name = "Name")] 
    public string Name { get; set; } 

    [Display(Name = "Hashtag")] 
    public string Hashtag { get; set; } 

    [Display(Name = "Namespaces")] 
    [Description("Separate namespaces by ','")] 
    public string Namespaces { get; set; } 

    [Required] 
    [AllowHtml] 
    [UIHint("MultilineText")] 
    [Display(Name = "Html")] 
    [Description("Prefix or sufix your razor variables with #")] 
    public string Html { get; set; } 

    [Timestamp] 
    [ConcurrencyCheck] 
    public byte[] RowVersion { get; set; } 
} 

控制器

[HttpPost] 
    public virtual ActionResult Edit(KeywordEditViewModel model, string @return) 
    { 
     var data = new JsonResultData(ModelState); 

     if (ModelState.IsValid) 
     { 
      data.RunWithTry((resultData) => 
      { 
       KeywordManager.Update(model.KeywordId, model, CurrentUser.UserId); 
       resultData.RedirectUrl = !string.IsNullOrEmpty(@return) ? @return : Url.Action("Index"); 
      }); 
     } 

     return Json(data); 
    } 

業務

public KeywordModel Update(int id, object viewmodel, int userId) 
    { 
     var model = Get(id); 

     Mapper.Map(viewmodel, model); 
     SaveChanges("Update mailing keyword", userId); 

     return model; 
    } 

AutoMapper

CreateMap<KeywordModel, KeywordEditViewModel>(); 
CreateMap<KeywordEditViewModel, KeywordModel>(); 

在我的測試中,RowVersion領域在數據庫中不同的值,但SaveChange不會產生異常DbUpdateConcurrencyException。

SQL跟蹤

UPDATE [Mailing].[Keyword] 
SET [Namespaces] = @0, [audit_LastUpdate] = @1 
WHERE (([KeywordId] = @2) AND ([RowVersion] = @3)) 
SELECT [RowVersion] 
FROM [Mailing].[Keyword] 
WHERE @@ROWCOUNT > 0 AND [KeywordId] = @2 
@0: 'titi' (Type = String, Size = -1) 
@1: '09/11/2016 13:35:54' (Type = DateTime2) 
@2: '1' (Type = Int32) 
@3: 'System.Byte[]' (Type = Binary, Size = 8) 
+0

檢查該更新生成的sql(context.Database.Log = ...) – Evk

+0

您在視圖中有類似於@ Html.HiddenFor(m => m.RowVersion)的東西嗎? (我不知道automapper)所以,如果你保存,它就像你之前加載的rowversion一樣? –

+0

是的,在我看來,我有一個隱藏的輸入'RowVersion'。就在'SaveChange'之前,我的對象中的值與數據庫值不同,但更新正常工作... –

回答

0

優於從不遲到......

我尋找這個確切的情況在幾個小時後,解決了這個問題。 EF,automapper,viewmodels,全九。幾十篇文章之後,有人終於說出了一些讓我找到正確方向的東西,實際上這是一個很簡單的解決方法。

當你進行這個調用時:var model = Get(id); 要獲取當前的值,然後將更新映射到頂部,將選擇新的行版本。

解決的辦法是讓「Get(id)」選擇無需跟蹤。問題解決。在我的情況下,我的回購有一個「編輯(實體)」的方法,標記對象被修改,並附加它,如果它被分離。你也許可以在這裏做同樣的事情。