我不确定如何在EF 4.1 code first
中映射下面的表格以及我需要表示表格的对象。如何检索产品规格列表?
我目前只有一个Product
课程。
Products Table:
Id
Name
IsActive
ProductSpecification Table:
ProductId
SpecificationId
Specifications Table:
Id
Name
IsActive
ProductSpecifications
是一个关联表。我在上下文类中也定义了以下内容:
public DbSet<Product> Products { get; set; }
修改
请参阅我更新的原始帖子。我更改了产品和规格表的ID。
在我的上下文课中,我有以下内容:
public DbSet<Product> Products { get; set; }
public DbSet<Specification> Specifications { get; set; }
在我的存储库中,我有以下内容:
public Product GetById(int id)
{
return db.Products
.Include("Specifications")
.SingleOrDefault(x => x.Id == id);
}
我的Product class
(部分):
public class Product : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public ICollection<Specification> Specifications { get; set; }
}
我的Specification class
:
public class Specification : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public ICollection<Product> Products { get; set; }
}
这就是我从Slauma的回答中所做的一切。我并没有像他说的那样手动进行映射,但我首先要了解以下内容:
鉴于我上面的类和表,EF 4.1命名约定究竟是如何处理它如何处理关联表的?我问的原因是因为我的GetById方法中出现以下错误:
Invalid object name 'dbo.SpecificationProducts'.
编辑2
我忘了提及以下:)产品可以具有规格高度作为值。对于这个高度,我需要指定一个值。像100英寸。因此,我将ProductSpecifications表修改为具有名为SpecificationValue
的值列,此列将包含100英寸的值。我如何修改代码以检索此值?我需要在我的视图中显示它。
答案 0 :(得分:11)
在多对多关系中,您只为要关联的实体定义类,而不为关联表定义实体。此表在模型中“隐藏”,并由Entity Framework自动管理。所以你可以定义这些类:
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public ICollection<Specification> Specifications { get; set; }
}
public class Specification
{
public int SpecificationId { get; set; }
public string Name { get; set; }
public ICollection<Product> Products { get; set; }
}
这通常足以定义多对多关系。 EF将根据此映射创建连接表。如果您已在数据库中拥有此类表,并且其命名不完全遵循实体框架的命名约定,则可以在Fluent API中手动定义映射:
modelBuilder.Entity<Product>()
.HasMany(p => p.Specifications)
.WithMany(s => s.Products)
.Map(c =>
{
c.MapLeftKey("ProductId");
c.MapRightKey("SpecificationId");
c.ToTable("ProductSpecification");
});
修改强>
然后,您可以使用Include
加载产品的规格,例如:
var productWithSpecifications = context.Products
.Include(p => p.Specifications)
.SingleOrDefault(p => p.ProductId == givenProductId);
这会将产品与规格一起加载。如果您只需要给定产品ID的规格,则可以使用以下内容:
var specificationsOfProduct = context.Products
.Where(p => p.ProductId == givenProductId)
.Select(p => p.Specifications)
.SingleOrDefault();
...返回规范集合。
修改2
EF Code-First的命名约定将假定连接表的名称构建为两个相关类名的组合,然后将其复数。因此,如果没有明确映射到您的表名ProductSpecification
,EF将假设ProductSpecifications
(Plural)并使用该名称构建查询作为表名。由于数据库中不存在此表,因此在运行查询时会出现异常“无效对象名称'dbo.SpecificationProducts'。”。因此,您必须重命名数据库中的表或使用上面的映射代码。
编辑3
我强烈建议在任何情况下使用explicite映射,因为连接表名称EF假定为depends on the order of the DbSets in your context。通过更改这些集的顺序,连接表可以是SpecificationProducts
。如果没有明确表映射到固定表名,则在上下文中交换(通常不重要)集可能会破坏您的工作应用程序。