2012-04-27 3 views
5

Скажем, у нас есть:Как обращаться с EF 4.3.1 настройка модифицировали Rowversion Row

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

Сейчас в короткий I`m перед такой ситуацией.

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

И результат

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

Есть ли способ, который может заставить обновления на отдельный объект, или обходной путь для этого rowversion колонке не следует установить в качестве Modified.

ответ

7

Похоже, что вы не указали свойство stamp как rowversion в своей модели, и это просто двоичное поле. Вы можете указать его с Fluent API:

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

Код выше для случая, когда вы не хотите иметь stamp собственности в качестве маркеров параллелизма. (A rowversion является маркер параллелизм по умолчанию, так что вы должны отключить его в явном виде.) Если вы хотите, чтобы иметь его в качестве параллелизма маркеров, то вы можете использовать с Fluent API ...

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

... или с аннотациями данных:

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

Это должно помешать EF написать ОБНОВЛЕНИЕ для этого свойства.

Редактировать

При использовании базы данных первой стратегии атрибут [Timestamp] не работает. Этот атрибут предназначен только для разработки Code-First.

При использовании базы данных первой строки подключения содержит раздел метаданных отсылая к EDM, определенный в файле EDMX:

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

Если Entity Framework находит этот раздел в строке подключения он не использует данные аннотации на свойства модели и не обрабатывает какой-либо код в Fluent API (OnModelCreating вообще не вызывается). Вместо этого он загружает определения сопоставления из встроенного и скомпилированного файла EDMX.

Это означает, что если вы хотите определить свойство stamp как токен параллелизма, вы должны должен сделать это в файле EDMX. В XML это будет выглядеть следующим образом:

В разделе SSDL:

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

В разделе ЦДЦБЛ:

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

Вы также можете определить это в модели конструктора в Visual Studio: отметить stamp свойство в объекте на поверхности конструктора, перейдите в окно «Свойства» и установите «Режим параллелизма» на «Исправлено» (а также установите «StoreGeneratedPattern» на «Computed»).

Вы также можете удалить раздел метаданных из строки подключения.Но это фактически означает, что вы сначала переключаетесь с базы данных на первую разработку кода. Тогда все атрибуты и Fluent API будут соблюдаться, но никаких определений в EDMX больше не будет.

+0

Маркировка объекта как [отметки времени] не решает ничего. Проблема зависит от 'DBContext.Entry (entity) .State = EntityState.Modified;'. Он отмечает свойство штампа как измененное и в течение 'DBContext.SaveChanges()' он строит 'dynamic-sql *, который обновляет столбец [штамп] в БД. Это предположение для SQLCE. У меня нет профилировщика для его резервного копирования. –

+0

@CiobanuIon: для SQL Server это неверно. EF не отправляет SQL, который обновляет столбец свойства, помеченного как «[Timestamp]», вместо этого его значение включено в предложение WHERE для проверки оптимистичного параллелизма. Вы проверяли, что это не работает? Какую версию SQLCE вы используете? – Slauma

+0

Я использую SQLCE4.0.0.0. Теперь, когда я тестировал, работает ли параллелизм, это не так. С обычными несвязанными объектами обновление происходит, значение [штамп] увеличивается, но параллелизм не происходит. Это неожиданно. У меня есть первый случай с базой данных. Сгенерированные POCOклазы из EF4.x DbContext Generator и украсили их DataAnnotations. На самом деле не уверен, где искать сейчас. По предыдущему вопросу, я предполагал, что если я не могу установить Modified для всего объекта, я установил только некоторые свойства как Модифицированные, и обновление работало. Но жесткое кодирование для каждого свойства не является правильным решением. –