在继承TPC中具有相同主键的实体

时间:2015-06-16 13:00:04

标签: c# entity-framework inheritance

我在ASP.NET MVC 4中创建了一个网站,我有这个我无法理解的错误:

  

所有对象EntitySet'DataContext.Strategies'必须具有唯一的主键。但是,“AuctionSelling”类型的实例和“DirectSelling”类型的实例具有相同的主键值,'EntitySet = Strategies; Id = 0'。

所以这是主键问题,但我不明白为什么会发生这种情况。

我使用策略TPC进行继承,这是我的课程:

public abstract class SellingStrategy
{
    public long Id { get; set; }
    public DateTime SoldDate { get; set; }
    public abstract float getSoldPrice();
}


public class DirectSelling : SellingStrategy
{
    public float SoldPrice { get; set; }

    public override float getSoldPrice()
    {
        return SoldPrice;
    }
}


public class AuctionSelling : SellingStrategy
{
    public float BasePrice { get; set; }
    public DateTime EndOfAuction { get; set; }

    public override float getSoldPrice()
    {
        return BasePrice;
    }
}

这是我的背景:

public class DataContext : DbContext
{
    public DbSet<Article> Articles { get; set; }
    public DbSet<Utilisateur> Utilisateurs { get; set; }
    public DbSet<Adresse> Adresses { get; set; }

    public DbSet<SellingStrategy> Strategies { get; set; }

    public DataContext() : this ("DBAchatVente")
    {
    }

    public DataContext(string connectionString)
        : base(connectionString)
    {

    }

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

        modelBuilder.Entity<Article>().HasKey<long>(a => a.Id);
        modelBuilder.Entity<Article>().Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<Article>().Property(a => a.Nom).IsRequired();
        modelBuilder.Entity<Article>().Property(a => a.Description).IsRequired();
        modelBuilder.Entity<Article>().Property(a => a.UrlImage).IsRequired();

        modelBuilder.Entity<Article>().Ignore(a => a.IdVendeur);
        modelBuilder.Entity<Article>().Ignore(a => a.MailVendeur);
        modelBuilder.Entity<Article>().Ignore(a => a.MotDePasseVendeur);
        modelBuilder.Entity<Article>().Ignore(a => a.AdresseLivraisonVendeur);
        modelBuilder.Entity<Article>().Ignore(a => a.AdressePaiementVendeur);
        modelBuilder.Entity<Article>().Ignore(a => a.NomVendeur);
        modelBuilder.Entity<Article>().Ignore(a => a.PrenomVendeur);

        modelBuilder.Entity<Article>().Ignore(a => a.IdAcheteur);
        modelBuilder.Entity<Article>().Ignore(a => a.MailAcheteur);
        modelBuilder.Entity<Article>().Ignore(a => a.MotDePasseAcheteur);
        modelBuilder.Entity<Article>().Ignore(a => a.AdresseLivraisonAcheteur);
        modelBuilder.Entity<Article>().Ignore(a => a.AdressePaiementAcheteur);
        modelBuilder.Entity<Article>().Ignore(a => a.NomAcheteur);
        modelBuilder.Entity<Article>().Ignore(a => a.PrenomAcheteur);

        modelBuilder.Entity<Article>().HasOptional<Utilisateur>(u => u.UserAcheteur).WithMany().WillCascadeOnDelete(false);
        modelBuilder.Entity<Article>().HasRequired<Utilisateur>(u => u.UserVendeur).WithMany().WillCascadeOnDelete(false);

        modelBuilder.Entity<Article>().HasRequired<SellingStrategy>(a => a.Strategy).WithMany().WillCascadeOnDelete(false);
        modelBuilder.Entity<SellingStrategy>().Property(s => s.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        modelBuilder.Entity<AuctionSelling>().HasKey<long>(s => s.Id);            
        modelBuilder.Entity<AuctionSelling>().Map(m => {
            m.MapInheritedProperties();
            m.ToTable("AuctionSelling");
        });
        modelBuilder.Entity<DirectSelling>().HasKey<long>(s => s.Id);   
        modelBuilder.Entity<DirectSelling>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("DirectSelling");
        });
        modelBuilder.Entity<SellingStrategy>().Property<DateTime>(s => s.SoldDate).HasColumnName("DateVente").HasColumnType("datetime2").IsOptional();


        modelBuilder.Entity<Adresse>().HasKey<long>(a => a.Id);
        modelBuilder.Entity<Adresse>().Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<Adresse>().Property(a => a.Rue).IsRequired();
        modelBuilder.Entity<Adresse>().Property<long>(a => a.Numero).IsRequired();
        modelBuilder.Entity<Adresse>().Property(a => a.Localite).IsRequired();
        modelBuilder.Entity<Adresse>().Property(a => a.Pays).IsRequired();

        modelBuilder.Entity<Utilisateur>().HasKey<long>(u => u.Id);
        modelBuilder.Entity<Utilisateur>().Property(u => u.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<Utilisateur>().Property(u => u.Nom).IsRequired();
        modelBuilder.Entity<Utilisateur>().Property(u => u.Prenom).IsRequired();
        modelBuilder.Entity<Utilisateur>().Property(u => u.Mail).IsRequired();
        modelBuilder.Entity<Utilisateur>().Property(u => u.MotDePasse).IsRequired();

        modelBuilder.Entity<Utilisateur>().Ignore(u => u.RuePaiement);
        modelBuilder.Entity<Utilisateur>().Ignore(u => u.NumeroPaiement);
        modelBuilder.Entity<Utilisateur>().Ignore(u => u.LocalitePaiement);
        modelBuilder.Entity<Utilisateur>().Ignore(u => u.PaysPaiement);

        modelBuilder.Entity<Utilisateur>().Ignore(u => u.RueLivraison);
        modelBuilder.Entity<Utilisateur>().Ignore(u => u.NumeroLivraison);
        modelBuilder.Entity<Utilisateur>().Ignore(u => u.LocaliteLivraison);
        modelBuilder.Entity<Utilisateur>().Ignore(u => u.PaysLivraison);

        modelBuilder.Entity<Utilisateur>().HasRequired<Adresse>(a => a.AdresseLivraison).WithMany().WillCascadeOnDelete(false);
        modelBuilder.Entity<Utilisateur>().HasRequired<Adresse>(a => a.AdressePaiement).WithMany().WillCascadeOnDelete(false);
    }
}

当我尝试获取我的文章时会发生异常,即使每个策略位于不同的表中,也有2篇文章具有相同的策略ID。

using (DataContext context = new DataContext(connexion))
        {
            var con = from article in context.Articles.Include("UserVendeur").Include("UserAcheteur").Include("Strategy")
                      select article;
            listeArticle = con.ToList<Article>();
        }

这是

listeArticle = con.ToList<Article>();

引发错误。

1 个答案:

答案 0 :(得分:1)

我认为答案就在这里:https://msdn.microsoft.com/en-us/data/jj591617.aspx#2.6

基本上你不能有两个相同类型的对象(这里是你的基类)具有相同的PK。

要实现这一点,您必须使用不同的种子(例如0和Int32.MinValue)在数据库中设置AuctionSelling和DirectSelling表的标识。

在sql server中,所需的命令是:DBCC CHECKIDENT(DirectSelling,RESEED,1000000000)