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

时间:2011-11-01 11:51:13

标签: entity-framework ado.net entity-framework-4.1

我不确定如何在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英寸的值。我如何修改代码以检索此值?我需要在我的视图中显示它。

1 个答案:

答案 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。如果没有明确表映射到固定表名,则在上下文中交换(通常不重要)集可能会破坏您的工作应用程序。