1

Ich muss Nebenläufigkeit in unserem Framework verwalten, aber ich kann keine DbUpdateConcurrencyException generieren. Wir verwenden SQL Server 2008, EF 6 und AutoMapper 5.Concurrency Access, warum EntityFramework 6 eine DbUpdateConcurrencyException nicht generiert?

SQL

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

Modell

[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; } 
} 

Ansichtsmodell

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; } 
} 

-Controller

[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); 
    } 

Geschäft

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>(); 

In meinen Tests hat die RowVersion Felder einen anderen Wert in der Datenbank aber nicht Savechange Ausnahme DbUpdateConcurrencyException erzeugen.

SQL-Trace

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

Überprüfen Sie, welche SQL von diesem Update generiert wird (context.Database.Log = ...) – Evk

+0

Sie haben etwas wie '@ Html.HiddenFor (m => m.RowVersion)' in Ihrer Ansicht? (Ich kenne keinen AutoMapper) Also, wenn Sie speichern, ist es die gleiche Zeilenversion wie zuvor geladen? –

+0

Ja, ich habe eine versteckte Eingabe 'RowVersion' aus meiner Sicht. Kurz vor dem 'SaveChange' ist der Wert in meinem Objekt anders als der Datenbankwert, aber das Update funktioniert ... –

Antwort

0

Besser spät als nie ...

löste ich dieses Problem nach ein paar Stunden für diese genaue Szenario zu suchen. EF, Autofahrer, Viewmodels, die ganzen neun. Nach Dutzenden von Artikeln sagte schließlich jemand etwas, das mir die richtige Richtung und seine eigentlich recht einfache Lösung brachte.

Wenn Sie diesen Aufruf ausführen: var model = Get (id); Um Ihre aktuellen Werte abzurufen und die Aktualisierungen dann oben zuzuordnen, wird die neue Zeilenversion ausgewählt.

Die Lösung besteht darin, "Get (id)" ohne Tracking auszuwählen. Problem gelöst. In meinem Fall hatte mein Repo eine Methode für "Edit (entity)", die das Objekt als modifiziert markierte und es anschloss, wenn es gelöst wurde. Sie können das vielleicht auch hier tun.

Verwandte Themen