我正在使用EF 4.1 code first
,我正在努力处理关联实体并获取在关联表中设置的值。我试着关注帖子:Create code first, many to many, with additional fields in association table。
我的表格如下(全部为复数形式):
表:产品
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不会分别映射到产品的Id和规范的ID吗?
我如何退回具有所有规格的单一产品?
答案 0 :(得分:1)
实体框架将识别ProductId
是Product
导航属性的外键属性,而SpecificationId
是外键 Specification
导航属性的属性。但该异常会抱怨ProductSpecification
实体上缺少主键(“Key”=“Primary Key”)。每个实体都需要定义一个关键属性。这可以通过约定 - 通过键属性的特定命名 - 或明确使用数据注释或Fluent API来实现。
您的ProductSpecification
类没有按惯例将EF识别为关键字的属性:没有Id
属性而没有ProductSpecificationId
(类名+“Id”)。< / p>
所以你必须明确地定义它。使用数据注释定义它将显示在您链接的帖子中:
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);