使用实体框架代码优先方法时,还有一个附加表

时间:2014-05-10 11:06:04

标签: entity-framework ef-code-first

我使用Entity Framework代码第一种方法来创建mydatabase。我有四个简单的课程:

我的第一堂课是分类:

public class Category
{
    [Key]
    public int CategoryId { set; get; }        
    public DateTime CreatedOn { set; get; }    
    public int? ParentCategoryId { set; get; }    
    public virtual ICollection<Product> Products { set; get; }    
    public virtual ICollection<CategoryLanguage> CategoriesLanguages { set; get; }    
    public Category()
    {
        this.Products = new HashSet<Product>();
        this.CategoriesLanguages = new HashSet<CategoryLanguage>();
    }
}

我的第二课--CategoryLanguage.cs

public class CategoryLanguage
{
    [Key]
    public int Id { set; get; }    
    [Required]
    public string Title { set; get; }    
    public int CategoryId { set; get; }    
    public virtual Category Category { set; get; }    
    public int LanguageId { set; get; }
    public virtual Language Language { set; get; }
}

我的第三课 - Product.cs

public class Product
{       
    [Key]
    public int ProductId { set; get; }
    public decimal Price { set; get; }
    public int Quantity { set; get; }
    public string Image { set; get; }
    public virtual ICollection<Category> Categories { set; get; }
    public virtual ICollection<ProductLanguage> ProductLanguages { set; get; }
    public Product()
    {
        this.Categories = new HashSet<Category>();
        this.ProductLanguages = new HashSet<ProductLanguage>();
    }
}

和我的上一堂课

public class ProductLanguage
{
    [Key]
    public int Id { set; get; }
    public int ProductId { set; get; }
    public virtual Product Product { set; get; }
    public int LanguageId { set; get; }
    public virtual Language Language { get; get; }
    public string Name { set; get; }
    public string ShortDescription { set; get; }
    public string Description { set; get; }
}

这是我的DbContext

public class EcommerceDBContext:DbContext
{
    public EcommerceDBContext() : base("DefaultConnection"){}
    public DbSet<Category> Categories { set; get; }
    public DbSet<CategoryLanguage> CategoriesLanguages { set; get; }
    public DbSet<Product> Products { set; get; }
    public DbSet<ProductLanguage> ProductsLanguages { set; get; }
}

很奇怪在我的数据库中,我看到另一个表ProductCategories,其中有两列:Product_ProductIDCategory_CategoryID

因此,Product表和Categories表具有多对多的关系,而且我使用延迟加载是正确的,这是真的。能够加载Category的所有产品;以及产品的所有类别。我只是很好奇代码优先引擎如何决定制作这个表。 (在所有集合都是虚拟的之后,它们不应该存在于数据库中)。

2 个答案:

答案 0 :(得分:1)

您已用

字样回答了自己的问题
  

[产品表和类别表具有多对多关系

延迟加载和virtual无关 - virtual只是通过在运行时创建代理类型来启用延迟加载(请参阅下面的参考资料)。

代码优先只是检测到两个表与多对多关系链接,因为在每个类中,您具有相关类的ICollection属性:P有许多{{1 }和C有很多C。因此,它使用命名约定P创建连接表,并使用关系每一侧的主键列。

参考

请参阅MSDN:加载相关实体"Lazy Loading""Turning off lazy loading for specific navigation properties"<LeftTable><RightTable><plural modifier>几乎被提及为这些部分中的传递注释,但这是延迟加载的原因。

加入,链接或映射表,具体取决于您的偏好

答案 1 :(得分:0)

当EF Code First决定如何将模型类映射到数据库模式时,它会检查模型类,尤其是这些类之间的导航属性。在您的示例中,它发现Category有一个Products 集合(一个类别包含许多产品),并且产品有一个{{1} } 集合(一个产品有许多类别)。从此EF得出结论,两个实体之间的关系是多对多。为了将其映射到关系数据库,需要一个链接表,它是引入的Categories表。

当然还有更多细节可以控制映射 - 比如数据注释和Fluent API。但是对于您的具体示例,映射仅依赖于约定和类定义。

BTW:您的导航属性为ProductCategories并不重要。实体和数据库模式之间的映射与导航属性virtual(支持延迟加载)无关。