如何在使用TPT层次结构时首先在EF代码中实现并发

时间:2011-04-08 09:56:56

标签: .net inheritance sql-server-ce ef-code-first entity-framework-4.1

嘿大家好!我正在尝试首先使用实体​​框架代码实现乐观并发检查(通过nuget安装,因此我假设它是最后一个RC)。但是,我似乎无法使其发挥作用。我有以下类层次结构

public abstract class DbEntityBase
{
    /// <summary>
    /// Autogenerated primary key for the object
    /// </summary>
    public Guid Id { get; private set; }

    protected DbEntityBase()
    {
        Id = Guid.NewGuid();
    }

    //Some override for equality, omitted for brievity
}

public class Drawing : DbEntityBase
{
    public string Name { get; set; }

    //Just an implementation of ICollection<DrawingVersion>
    public DrawingVersionCollection Versions { get; private set; }

    public Drawing()
    {
        Name = "New Drawing";
        Versions = new DrawingVersionCollection(this);         
    }

}

public class DrawingVersion : DbEntityBase
{
    public string Name { get; set; }

    public DateTime Started { get; set; }

    public DateTime LastModified { get; set; }

    public DrawingFile File { get; private set; }

    public Drawing Owner { get; internal set; }

    internal DrawingVersion()
    {
        Name = "New Version";
        Started = DateTime.Now;
        LastModified = DateTime.Now;
        File = new DrawingFile();
    }
}

我正在使用以下DbContext来保留它们

public class PortfolioContext : DbContext
{
    public DbSet<Drawing> Drawings { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Key mapping
        modelBuilder.Entity<DbEntityBase>()
            .HasKey(e => e.Id);

        //Table Mapping
        modelBuilder.Entity<DrawingVersion>().ToTable("DrawingVersion");
        modelBuilder.Entity<Drawing>().ToTable("Drawing");

        //Ignored fields
        modelBuilder.Entity<DrawingVersion>()
            .Ignore(v => v.Owner);
    }
}

这一切工作都很好,花花公子。如果我检查生成的模式,我会看到表格,一个用于绘图,一个用于DrawingVersion。我可以毫无问题地阅读,更新和删除。

当我想为我的实体添加时间戳时出现问题。起初我做了天真的事。我在DbEntityBase中添加了以下内容

    public byte[] Timestamp { get; set; }

在我的背景下那些行

        //Versionning mapping
        modelBuilder.Entity<DbEntityBase>()
            .Property(e => e.Timestamp)
            .IsConcurrencyToken()
            .HasColumnType("timestamp")
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);

但是,在模式生成期间,它会因以下异常而失败

  

System.NotSupportedException:The   商店生成的模式'计算'是   不支持属性   不是'timestamp'类型或   'rowversion'。

那时我有点神圣。 “好吧,我就是这样,把 timestamp 放在列类型中,而我应该把 timestamp 改为”。我试过把'rowversion'代替,把它仍然无效。我也直接在属性上尝试了TimestampAttribute,但是同样的错误。

我尝试将时间戳数据放在子类上,但后来我遇到了以下异常

  

System.Data.Entity.ModelConfiguration.ModelValidationException   :一个或多个验证错误   在模型生成期间检测到

     

System.Data.Edm.EdmEntityType :: Type   'Portfolio.Repositories.Drawing'是   派生自该类型   'Portfolio.Repositories.DbEntityBase'   这是EntitySet的类型   'PortfolioContext.DbEntityBases'。类型   'Portfolio.Repositories.Drawing'   定义新的并发要求   不允许子类型的   基本的EntitySet类型。

所以我想我也做不到。

我必须说,我很困惑。为什么异常告诉我应该使用时间戳,因为它正是我正在做的事情?这可能是框架中的错误吗?如果不是,是否可以通过Table PerType映射添加并发检查?

我使用SQL Serve Ce 4.0作为我的数据库。

1 个答案:

答案 0 :(得分:1)

这看起来像是定义TPC继承的问题。您必须修改子实体映射以使用父实体的映射:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    ...

    modelBuilder.Entity<DrawingVersion>()
                .Map(m => m.MapInheritedProperties())
                .ToTable("DrawingVersion");

    modelBuilder.Entity<Drawing>()
                .Map(m => m.MapInheritedProperties())
                .ToTable("Drawing");

    ...
}