首先映射EF 4.1代码中的关联表

Bre*_*ogt 6 ado.net entity-framework entity-framework-4.1

我不确定如何映射下面的表格EF 4.1 code first以及我需要表示表格的对象.我如何检索产品规格列表?

我目前只Product上课了.

Products Table:
Id
Name
IsActive

ProductSpecification Table:
ProductId
SpecificationId

Specifications Table:
Id
Name
IsActive
Run Code Online (Sandbox Code Playgroud)

ProductSpecifications是一个关联表.我的上下文类中也定义了以下内容:

public DbSet<Product> Products { get; set; }
Run Code Online (Sandbox Code Playgroud)

编辑

请参阅我更新的原始帖子.我更改了产品和规格表的ID.

在我的上下文课中,我有以下内容:

public DbSet<Product> Products { get; set; }
public DbSet<Specification> Specifications { get; set; }
Run Code Online (Sandbox Code Playgroud)

在我的存储库中,我有以下内容:

public Product GetById(int id)
{
     return db.Products
          .Include("Specifications")
          .SingleOrDefault(x => x.Id == id);
}
Run Code Online (Sandbox Code Playgroud)

我的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; }
}
Run Code Online (Sandbox Code Playgroud)

我的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; }
}
Run Code Online (Sandbox Code Playgroud)

这就是我从Slauma的回答中所做的一切.我没有按照他说的那样手动进行映射,但我首先需要了解以下内容:

鉴于我上面的类和表,EF 4.1命名约定究竟是如何处理它如何处理关联表的?我问的原因是因为我的GetById方法中出现以下错误:

Invalid object name 'dbo.SpecificationProducts'.
Run Code Online (Sandbox Code Playgroud)

编辑2

我忘了提及以下:)产品可以具有规格高度作为值.对于这个高度,我需要指定一个值.像100英寸.所以我修改了ProductSpecifications表以调用一个值列SpecificationValue,该列将包含100英寸的值.我如何修改代码以检索此值?我需要在我的视图中显示它.

Sla*_*uma 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; }
}
Run Code Online (Sandbox Code Playgroud)

这通常足以定义多对多关系.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");
        });
Run Code Online (Sandbox Code Playgroud)

编辑

然后,您可以使用Include以下方式加载产品的规格:

var productWithSpecifications = context.Products
    .Include(p => p.Specifications)
    .SingleOrDefault(p => p.ProductId == givenProductId);
Run Code Online (Sandbox Code Playgroud)

这会将产品与规格一起加载.如果您只需要给定产品ID的规格,则可以使用以下内容:

var specificationsOfProduct = context.Products
    .Where(p => p.ProductId == givenProductId)
    .Select(p => p.Specifications)
    .SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)

...返回一系列规范.

编辑2

EF Code-First的命名约定将假定连接表的名称构建为两个相关类名的组合,然后将其复数.因此,如果没有明确映射到您的表名,ProductSpecificationEF将假设ProductSpecifications(Plural)并使用该名称构建查询作为表名.由于数据库中不存在此表,因此在运行查询时会出现" 无效对象名称'dbo.SpecificationProducts'. " 异常.因此,您必须重命名数据库中的表或使用上面的映射代码.

编辑3

我强烈建议在任何情况下都使用explicite映射,因为连接表名称EF 取决于上下文中DbSets的顺序.通过更改连接表的那些集的顺序SpecificationProducts.如果没有明确的映射到固定的表名,则上下文中的集合(通常不重要)交换可能会破坏您的工作应用程序.