2013-09-11 5 views
3

Я использую Entity Framework Code First 5 и у меня есть следующие модели для производителей автомобилей, легковых автомобилей и грузовиков:Невозможно определить основной конец отношений - Несколько добавленных объекты могут иметь один и тот же первичный ключ

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_Associatio ns.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: 

Как бы идти об указании принцип конца этого отношения?

Я попытался добавить следующую конфигурацию с помощью модели строителя беглого API, но без успеха:

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

ответ

2

Вы должны иметь только один внешний ключ свойства вашего класса Производителя: Транспортные средства.

[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 будет генерировать дополнительный Дискриминатор столбец со значениями, взятыми из имен подкласса (Car , Грузовик) в вашем Автомобиль стол.

Для удобства, вы можете создать два дополнительных (не-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(); 
    } 
} 
+0

что делать, если у меня есть еще одна модель под названием «Производитель2», которая выглядит точно так же, как Производитель, со списком транспортных средств? У меня есть что-то похожее, но с 2 классами, которые похожи на класс производителя, и у них обоих есть класс, похожий на автомобиль, и у меня такое же исключение, см. Мой пост здесь http://stackoverflow.com/questions/26783934/foreign -Основные-циклы или каскадный-путь –

0

Я тестировал с использованием 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; } 

} 
Смежные вопросы

 Смежные вопросы