4

Я использую EF 4.1 code first, и я борюсь с объектом ассоциации и получаю значение, которое было установлено в таблице ассоциаций. Я попытался следить за сообщением: Create code first, many to many, with additional fields in association table.Извлечение значения в таблице ассоциаций в коде Entity Framework сначала

Мои таблицы следующим образом (все они находятся в форме множественного числа):

Таблица: Продукты

Id int 
Name varchar(50) 

Таблица: Технические характеристики

Id int 
Name varchar(50) 

Таблица: ProductSpecifications

ProductId int 
SpecificationId int 
SpecificationValue varchar(50) 

Мои связанные классы:

public class Product : IEntity 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<ProductSpecification> ProductSpecifications { get; set; } 
} 

public class Specification : IEntity 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<ProductSpecification> ProductSpecifications { get; set; } 
} 

public class ProductSpecification 
{ 
    public int ProductId { get; set; } 
    public virtual Product Product { get; set; } 
    public int SpecificationId { get; set; } 
    public virtual Specification Specification { get; set; } 
    public string SpecificationValue { get; set; } 
} 

Мой контекст Класс:

public class MyContext : DbContext 
{ 
    public DbSet<Product> Products { get; set; } 
    public DbSet<Specification> Specifications { get; set; } 
    public DbSet<ProductSpecification> ProductSpecifications { get; set; } 

    protected override void OnModelCreating(DbModelBuilder dbModelBuilder) 
    { 
    } 
} 

Мой вместилище метод, где я делаю вызов (не уверен, что это правильно):

public class ProductRepository : IProductRepository 
{ 
    MyContext db = new MyContext(); 

    public Product GetById(int id) 
    { 
      var product = db.Products 
       .Where(x => x.Id == id) 
       .Select(p => new 
       { 
        Product = p, 
        Specifications = p.ProductSpecifications.Select(s => s.Specification) 
       }) 
       .SingleOrDefault(); 

      return null; // It returns null because I don't know how to return a Product object? 
    } 
} 

Здесь вы ошибка, которую я возвращаю:

One or more validation errors were detected during model generation: 

System.Data.Edm.EdmEntityType: : EntityType 'ProductSpecification' has no key defined. Define the key for this EntityType. 
System.Data.Edm.EdmEntitySet: EntityType: EntitySet �ProductSpecifications� is based on type �ProductSpecification� that has no keys defined. 

Что означает, что ключи не определены? Не будет ли ProductId и SpecificationId отображать идентификатор продукта и идентификатор спецификации соответственно?

Как я могу вернуть один продукт со всеми его спецификациями?

ответ

1

Entity Framework будет признать, что ProductId является внешним ключом свойства для Product свойства навигации и SpecificationId является внешним ключом свойства для Specification свойства навигации. Но исключение жалуется на отсутствующий первичный ключ («Ключ» = «Основной ключ») на вашем объекте ProductSpecification. Каждому объекту требуется определенное свойство ключа. Это может происходить либо по условным обозначениям - по конкретному наименованию свойства ключа, либо по простоте с аннотациями данных или Fluent API.

Ваш класс ProductSpecification не имеет свойства, которое EF распознает в качестве ключа по соглашению: нет Id и ProductSpecificationId (имя класса + «идентификатор»).

Значит, вы должны определить это явно. Определение его с аннотациями данных показано в посте вы связаны:

public class ProductSpecification 
{ 
    [Key, Column(Order = 0)] 
    public int ProductId { get; set; } 
    public virtual Product Product { get; set; } 

    [Key, Column(Order = 1)] 
    public int SpecificationId { get; set; } 
    public virtual Specification Specification { get; set; } 

    public string SpecificationValue { get; set; } 
} 

И Fluent API было бы:

modelBuilder.Entity<ProductSpecification>() 
    .HasKey(ps => new { ps.ProductId, ps.SpecificationId }); 

Оба способа определения составного ключа и каждая из частей является внешним ключом к таблице Product или Specification в то же время. (Вам не нужно явно определять свойства FK, потому что EF распознает его из-за своих дружественных к конвенции имен.)

Вы можете вернуть товар, включая все спецификации с жадной загрузкой, например:

var product = db.Products 
    .Include(p => p.ProductSpecifications.Select(ps => ps.Specification)) 
    .SingleOrDefault(x => x.Id == id); 
Смежные вопросы