【问题标题】:Unable to determine the principal end of the relationship - Multiple added entities may have the same primary key无法确定关系的主体端 - 多个添加的实体可能具有相同的主键
【发布时间】:2013-09-15 15:10:18
【问题描述】:

我正在使用 Entity Framework 5 Code First,我有以下适用于汽车制造商、汽车和卡车的模型:

public class Manufacturer
{
    public int Id { get; set; }
    public string Name { get; set; }

    [ForeignKey("ManufacturerId")]
    public virtual List<Car> Cars { get; set; }
    [ForeignKey("ManufacturerId")]
    public virtual List<Truck> Trucks { get; set; }
}

public class Vehicle
{
    public int Id { get; set; }
    public string Colour { get; set; }
    public int ManufacturerId { get; set; }
    public virtual Manufacturer Manufacturer { get; set; }
}

public class Car : Vehicle
{ }

public class Truck : Vehicle
{ }

public class Context : DbContext
{
    public DbSet<Manufacturer> Manufacturers { get; set; }
    public DbSet<Vehicle> Vehicles { get; set; }
}

为了开发和测试,我将数据播种如下:

public class DbInitialiser : DropCreateDatabaseAlways<Context>
{
    protected override void Seed(Context context)
    {
        var manufacturers = new List<Manufacturer>
        { 
            new Manufacturer
                {
                    Name = "Test Manufacturer",
                    Cars = new List<Car>
                        {
                            new Car { Colour = "Blue" },
                            new Car { Colour = "Green" }
                        },
                    Trucks = new List<Truck>
                        {
                            new Truck { Colour = "Red" }
                        }
                },
            new Manufacturer
                {
                    Name = "Another Manufacturer",
                    Cars = new List<Car>
                        {
                            new Car { Colour = "Pink" }
                        }
                }
        };

        manufacturers.ForEach(x => context.Manufacturers.Add(x));
    }
}

但是,当我使用上下文时,会出现以下异常: 无法确定“EF_Associations.Vehicle_Manufacturer”关系的主体端。多个添加的实体可能具有相同的主键。

堆栈跟踪:

System.Data.DataException was unhandled
HResult=-2146233087
Message=An exception occurred while initializing the database. See the InnerException for details.
Source=EntityFramework
StackTrace:
   at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)
   at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()
   at System.Data.Entity.Internal.LazyInternalContext.<InitializeDatabase>b__4(InternalContext c)
   at System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()
   at System.Data.Entity.Internal.InternalContext.Initialize()
   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
   at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
   at System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator()
   at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator()
   at EF_Associations.Program.Main(String[] args) in c:\temp\EF-Associations\Program.cs:line 19
   ...
InnerException: System.Data.Entity.Infrastructure.DbUpdateException
   HResult=-2146233087
   Message=Unable to determine the principal end of the 'EF_Associations.Vehicle_Manufacturer' relationship. Multiple added entities may have the same primary key.
   Source=EntityFramework
   StackTrace:
        at System.Data.Entity.Internal.InternalContext.SaveChanges()
        at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
        at System.Data.Entity.DbContext.SaveChanges()
        at System.Data.Entity.DropCreateDatabaseAlways`1.InitializeDatabase(TContext context)
        at System.Data.Entity.Database.<>c__DisplayClass2`1.<SetInitializerInternal>b__0(DbContext c)
        at System.Data.Entity.Internal.InternalContext.<>c__DisplayClass8.<PerformDatabaseInitialization>b__6()
        at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)
   InnerException: System.Data.UpdateException
        HResult=-2146233087
        Message=Unable to determine the principal end of the 'EF_Associations.Vehicle_Manufacturer' relationship. Multiple added entities may have the same primary key.
        Source=System.Data.Entity
        StackTrace:
             at System.Data.Mapping.Update.Internal.UpdateTranslator.RegisterEntityReferentialConstraints(IEntityStateEntry stateEntry, Boolean currentValues)
             at System.Data.Mapping.Update.Internal.UpdateTranslator.RegisterReferentialConstraints(IEntityStateEntry stateEntry)
             at System.Data.Mapping.Update.Internal.UpdateTranslator.PullModifiedEntriesFromStateManager()
             at System.Data.Mapping.Update.Internal.UpdateTranslator.ProduceCommands()
             at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
             at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)
             at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
             at System.Data.Entity.Internal.InternalContext.SaveChanges()
        InnerException: 

我将如何指定这种关系的原则结束?

我尝试通过模型构建器 fluent API 添加以下配置,但没有成功:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Vehicle>()
        .HasRequired(v => v.Manufacturer)
        .WithRequiredDependent();
}

【问题讨论】:

    标签: entity-framework ef-code-first entity-framework-5


    【解决方案1】:

    您的 Manufacturer 类中必须只有一个外键属性:Vehicles。

    [ForeignKey("ManufacturerId")]
    public virtual List<Vehicle> Vehicles { get; set; }
    

    您必须修改您的种子方法以使用这个单一的 FK 属性。 EF 将创建一个从您的实体类的继承链推断出的按层次结构表模型:

    protected override void Seed(Context context)
    {
        var manufacturers = new List<Manufacturer>
        { 
            new Manufacturer
                {
                    Name = "Test Manufacturer",
                    Vehicles = new List<Vehicle>
                        {
                            new Car {Colour = "Blue" },
                            new Car {Colour = "Green" },
                            new Truck {Colour = "Red" }
                        }
                },
            new Manufacturer
                {
                    Name = "Another Manufacturer",
                    Vehicles = new List<Vehicle>
                        {
                            new Car {Colour = "Pink" }
                        }
                }
        };
    
        manufacturers.ForEach(x => context.Manufacturers.Add(x));
        context.SaveChanges();
    }
    

    按照惯例,EF 将生成一个额外的 Discriminator 列,其值取自您的 中的子类名称(CarTruck) >车辆表。

    为方便起见,您可以在 Manufacturer 上创建两个附加(非 FK)属性,每个属性都包装一个特定于继承的 OfType 查询:

    public IEnumerable<Car> Cars
    {
        get
        {
            return this.Vehicles.OfType<Car>();
        }
    }
    
    public IEnumerable<Truck> Trucks
    {
        get
        {
            return this.Vehicles.OfType<Truck>();
        }
    }
    

    并使用它们进行查询:

    using (var db = new Context())
    {
        foreach (var manufacturer in db.Manufacturers)
        {
            var cars = manufacturer.Cars.ToList();
            var trucks = manufacturer.Trucks.ToList();
        }
    }
    

    【讨论】:

    • 如果我有另一个名为“Manufacturer2”的模型,它看起来与制造商完全一样,并带有车辆列表,该怎么办?我有类似的东西,但有 2 个类类似于制造商类,它们都有类似车辆的类,我遇到了同样的异常,请参阅我的帖子stackoverflow.com/questions/26783934/…
    【解决方案2】:

    我使用 SQL Server 2012 和“迁移”(http://msdn.microsoft.com/en-us/data/jj591621.aspx) 进行了测试

    对他们的类建模如下:

    [Table("Manufacturer")]
    public class Manufacturer
    {
       public Funcionario()
       {
         Cars = new List<Car>();
         Trucks = new List<Truck>();
       }
    
        [Key]
        [Required]
        [Column("Id", TypeName = "INT")]
        public int Id { get; set; }
    
        [Column("Name", TypeName = "VARCHAR")]
        public string Name { get; set; }
    
        public virtual ICollection<Car> Cars  { get; set; }
        public virtual ICollection<Truck> Trucks { get; set; }
     }
    
     [Table("Vehicle")]
     public class Vehicle
     {
       [Key]
       [Required]
       [Column("Id", TypeName = "INT")]
       public int Id { get; set; }
    
       [Column("Colour", TypeName = "VARCHAR")]
       public string Colour { get; set; }
    
       [Column("ManufacturerId", TypeName = "INT")]
       public int ManufacturerId { get; set; }
    
       [ForeignKey("ManufacturerId")]
       public virtual Manufacturer Manufacturer { get; set; }
      }
    
     [Table("Car")]
     public class Car : Vehicle
     { }
    
     [Table("Truck")]
     public class Truck : Vehicle
     { }
    
     public class Context : DbContext
     {
        public DbSet<Manufacturer> Manufacturers { get; set; }
        public DbSet<Vehicle> Vehicles { get; set; }
        public DbSet<Car> Cars { get; set; }
        public DbSet<Truck> Trucks { get; set; }
    
     }
    

    【讨论】:

      猜你喜欢
      • 2016-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-16
      • 2011-08-27
      • 2018-02-08
      相关资源
      最近更新 更多