2012-04-27 5 views
5

Digamos que tenemos:Cómo manejar EF 4.3.1 ajuste modificado un rowversion Fila

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

Ahora en fin yo estoy frente a este tipo de situación.

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

Y el resultado es

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

¿Hay algún método que podría forzar una actualización de una entidad individual, o una solución para esta columna rowversion No es para ponerla en su versión modificada.

Respuesta

7

Parece que no ha especificado la propiedad stamp como una versión de fila en su modelo y es solo un campo binario. Puede especificar con API Fluido:

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

El código anterior es para el caso en que no quiere tener la propiedad stamp como muestra la concurrencia. (A rowversion es una muestra de concurrencia por defecto, así que hay que desactivar de forma explícita.) Si usted quiere tener como símbolo de concurrencia, entonces se puede utilizar con la API Fluido ...

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

... o con anotaciones de datos:

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

Esto debería evitar que EF escriba una ACTUALIZACIÓN para esta propiedad.

Editar

Si utiliza la base de datos-Primera estrategia del atributo [Timestamp] no funciona. Este atributo es solo para desarrollo de Código Primero.

Cuando se utiliza la base de datos-En primer lugar la cadena de conexión contiene una sección de metadatos refiriéndose a la EDM se define en el archivo EDMX:

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

Si Entity Framework encuentra esta sección en la cadena de conexión que no utiliza los datos anotaciones sobre las propiedades del modelo ni procesa ningún código en Fluent API (OnModelCreating no se llama en absoluto). En su lugar, carga las definiciones de asignación del archivo EDMX incrustado y compilado.

Esto significa que si desea definir la propiedad stamp como un token de simultaneidad, debe hacer esto en el archivo EDMX. En XML se vería así:

en la sección SSDL:

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

en la sección CSDL:

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

También puede definir esto en el diseñador de modelos en Visual Studio: Marque la stamp propiedad en la entidad en la superficie del diseñador, vaya a la Ventana de Propiedades y configure "Modo Concurrencia" en "Fijo" (y también configure "StoreGeneratedPattern" en "Computado").

También puede eliminar la sección de metadatos de la cadena de conexión.Pero esto significa que usted cambia de la base de datos primero al primer desarrollo del código. Entonces todos los atributos y la API Fluent serán respetados, pero ya no habrá más definiciones en EDMX.

+0

Marcar la propiedad como [Timestamp] no resuelve nada. El problema se basa en 'DBContext.Entry (entidad) .State = EntityState.Modified;'. Marca la propiedad de sello como Modificada y durante 'DBContext.SaveChanges()' build's the * dynamic-sql * que actualiza la columna [stamp] en el DB. Esta es una causa adivinar de SQLCE No tengo un generador de perfiles para respaldarlo. –

+0

@CiobanuIon: para SQL Server esto no es cierto. EF no envía un SQL que actualiza una columna de una propiedad marcada con '[Timestamp]', sino que su valor se incluye en la cláusula WHERE para una comprobación de concurrencia optimista. ¿Has probado que no funciona? ¿Qué versión de SQLCE estás usando? – Slauma

+0

Estoy usando SQLCE4.0.0.0. Ahora que probé si la concurrencia funciona, no es así. Con las entidades habituales no separadas, la actualización está ocurriendo, el valor de [sello] se está incrementando pero la concurrencia no está sucediendo. Esto es inesperado. Tengo un primer caso de base de datos. Se generaron POCOclases de EF4.x DbContext Generator y se decoraron con DataAnnotations. Realmente no estoy seguro de dónde mirar ahora. Sobre el asunto anterior, mi suposición era que si no puedo establecer Modificado para toda la entidad, establecí solo algunas propiedades como Modificadas, y la actualización funcionó. Pero la codificación rigurosa para cada propiedad no es una solución adecuada. –

Cuestiones relacionadas