5

假设我们有:

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

现在简而言之,我正面临这种情况。

 ...
 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列设置为已修改的解决方法。

4

1 回答 1

7

看起来您没有stamp在模型中将该属性指定为 rowversion,它只是一个二进制字段。您可以使用 Fluent API 指定它:

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

上面的代码适用于您不希望将stamp属性用作并发令牌的情况。(默认情况下,rowversion 是一个并发令牌,因此您必须明确禁用它。)如果您想将它作为并发令牌,那么您可以使用 Fluent API...

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

...或带有数据注释:

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

这应该会阻止 EF 为该属性写入 UPDATE。

编辑

如果您使用 Database-First 策略,则该[Timestamp]属性不起作用。此属性仅适用于 Code-First 开发。

当您使用 Database-First 时,连接字符串包含一个引用 EDMX 文件中定义的 EDM 的元数据部分:

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

如果实体框架在连接字符串中找到此部分,它不会在模型属性上使用数据注释,也不会处理 Fluent API 中的任何代码(OnModelCreating根本不调用)。相反,它从嵌入和编译的 EDMX 文件加载映射定义。

这意味着,如果要将stamp属性定义为并发令牌,则必须在 EDMX 文件中执行此操作。在 XML 中,它看起来像这样:

在 SSDL 部分:

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

在 CSDL 部分:

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

您也可以在 Visual Studio 的模型设计器中定义它:stamp在设计器表面中标记实体中的属性,转到“属性”窗口并将“并发模式”设置为“固定”(并将“StoreGeneratedPattern”设置为“计算” ”)。

您还可以从连接字符串中删除元数据部分。但这实际上意味着您从数据库优先切换到代码优先开发。然后将尊重所有属性和 Fluent API,但不再是 EDMX 中的任何定义。

于 2012-04-27T16:33:32.423 回答