2012-04-27 4 views
5

Sagen wir:Wie EF 4.3.1 zu handhaben eine Rowversion Row geänderte Einstellung

public class Driver 
{ 
    public int driverID { get; set; } 
    public byte[] stamp { get; set; } 
    public string name { get; set; } 
    public string prename { get; set; } 
} 

Jetzt kurz I`m diese Art von Situation.

... 
var myDriver = myCustomDBContext.Drivers.AsNoTracking() 
             .Where(d => d.driverID == driverID) 
             .SingleOrDefault(); 
... 
myDriver.name = "John"; 
myDriver.prename = "Lennon"; 
... 
myCustomDBContext.Drivers.Attach(myDriver); 
myCustomDBContext.Entry(myDriver).State = EntityState.Modified; 
myCustomDBContext.SaveChanges(); 
... 

Und das Ergebnis ist

The column cannot be modified because it is an identity, rowversion or 
    a system column. [Column name = stamp] 

Gibt es eine Methode, die ein Update auf eine freistehende Einheit zwingen könnte, oder eine Abhilfe für dieses rowversion Spalte nicht festgelegt werden, wie Modified.

Antwort

7

Es sieht so aus, als hätten Sie die stamp-Eigenschaft nicht als Zeilenversion in Ihrem Modell angegeben, und es ist nur ein Binärfeld. Sie können es mit Fluent API angeben:

modelBuilder.Entity<Driver>().Property(d => d.stamp) 
    .IsRowVersion() 
    .IsConcurrencyToken(false); 

Der Code oben für den Fall ist, wenn Sie wollen nicht die stamp Eigenschaft als Gleichzeitigkeit Token haben. (A rowversion ist eine Gleichzeitigkeit Token standardmäßig so haben Sie es explizit zu deaktivieren.) Wenn Sie es als Gleichzeitigkeit Token haben wollen, dann können Sie mit Fluent API verwenden ...

modelBuilder.Entity<Driver>().Property(d => d.stamp) 
    .IsRowVersion(); 

... oder mit Datenanmerkungen:

[Timestamp] 
public byte[] stamp { get; set; } 

Dies sollte verhindern, dass EF ein UPDATE für diese Eigenschaft schreibt.

bearbeiten

Wenn Sie Datenbank-First-Strategie verwenden, die [Timestamp] Attribut funktioniert nicht. Dieses Attribut ist nur für Code-First-Entwicklung.

Wenn Sie Datenbank-Zuerst werden die Verbindungszeichenfolge enthält einen Metadaten-Abschnitt refering zum EDM definiert in der EDMX-Datei:

connectionString="metadata=res://*/Model1.csdl 
          |res://*/Model1.ssdl 
          |res://*/Model1.msl; 
          ... 
          ..." 

Wenn Entity Framework diesen Abschnitt im String-Verbindung findet es keine Daten verwenden Anmerkungen zu Modelleigenschaften und verarbeitet keinen Code in Fluent API (OnModelCreating wird überhaupt nicht aufgerufen). Stattdessen lädt es die Mapping-Definitionen aus der eingebetteten und kompilierten EDMX-Datei.

Das heißt, wenn Sie die stamp Eigenschaft als Concurrency Token definieren möchten, müssen Sie dies in der EDMX-Datei tun. In XML würde es so aussehen:

In SSDL Abschnitt:

<Property Name="stamp" Type="timestamp" Nullable="false" 
      StoreGeneratedPattern="Computed" /> 

In CSDL Abschnitt:

<Property Name="stamp" Type="Binary" Nullable="false" MaxLength="8" 
      FixedLength="true" 
      annotation:StoreGeneratedPattern="Computed" 
      ConcurrencyMode="Fixed" /> 

Sie können dies auch im Modell-Designer in Visual Studio definieren: Markieren Sie die stamp Eigenschaft in der Entity in der Designeroberfläche, gehen Sie zum Eigenschaftenfenster und setzen Sie "Concurrency Mode" auf "Fixed" (und setzen Sie auch "StoreGeneratedPattern" auf "Computed").

Sie können den Metadatenabschnitt auch aus der Verbindungszeichenfolge entfernen.Aber das bedeutet effektiv, dass Sie zuerst von der Datenbank zur ersten Code-Entwicklung wechseln. Dann werden alle Attribute und Fluent API respektiert, aber keine Definitionen in EDMX mehr.

+0

Das Markieren der Eigenschaft als [Timestamp] löst nichts. Das Problem beruht auf dem 'DBContext.Entry (entity) .State = EntityState.Modified;'. Es markiert die Stamp-Eigenschaft als Modified und während 'DBContext.SaveChanges()' erstellt es das * dynamic-sql *, das die Spalte [stamp] in der Datenbank aktualisiert. Dies ist eine Ursache für SQLCE Ich habe keinen Profiler, um es zu sichern. –

+0

@CiobanuIon: Für SQL Server ist dies nicht wahr. EF sendet kein SQL, das eine Spalte einer Eigenschaft aktualisiert, die mit '[Timestamp]' markiert ist, stattdessen wird ihr Wert in die WHERE-Klausel für die Prüfung der optimistischen Gleichzeitigkeit einbezogen. Hast du getestet, dass es nicht funktioniert? Welche Version von SQLCE verwenden Sie? – Slauma

+0

Ich verwende SQLCE4.0.0.0. Jetzt, wo ich getestet habe, ob Nebenläufigkeit funktioniert, ist es nicht. Bei normalen nicht-getrennten Entitäten wird die Aktualisierung durchgeführt, der [stamp] -Wert erhöht sich, aber die Nebenläufigkeit tritt nicht auf. Das ist unerwartet. Ich habe eine Datenbank ersten Fall. Generierte POCOclases von EF4.x DbContext Generator und dekoriert sie mit DataAnnotations. Wirklich unsicher, wo man jetzt hinschauen sollte. In der vorherigen Frage war meine Vermutung, wenn ich Modified nicht auf die gesamte Entity setzen kann, habe ich nur einige Eigenschaften als Modified gesetzt und die Aktualisierung funktioniert. Aber eine Codierung für jede Eigenschaft ist keine richtige Lösung. –