modelBuilder.Configurations.Add 和 modelBuilder.Entity 在 OnModelCreating

modelBuilder.Configurations.Add and modelBuilder.Entity on OnModelCreating

我刚刚开始研究 entity framework 代码优先方法,我在下面编写了两种方法并且都工作正常。

请告诉我这两种方法背后的核心概念是什么,应该遵循什么?

方法 1:使用 EntityTypeConfiguration

public class BlogsMap : EntityTypeConfiguration<Blog>
    {
        public BlogsMap(string schema)
        {
            ToTable("BLOG");
            HasKey(t => t.BlogId);
            Property(t => t.BlogId).HasColumnName("BLOGID");
            Property(t => t.Name).HasColumnName("NAME");
            Property(t => t.Url).HasColumnName("URL");
        }

    }


public class BlogContext : DbContext
    {
        public BlogContext(string name)
            : base(name)
        {
        }

        public IDbSet<Blog> BLOG { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
           modelBuilder.Configurations.Add(new BlogMap(string.Empty));
        }
    }

方法二:

public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }
        public string Url { get; set; }
        public virtual List<Post> Posts { get; set; }
    }


    public class BloggingContext : DbContext
    {     

        public DbSet<Blog> Blogs { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>();

        }
    }

请提供实体concept/blogs,因为我刚刚开始。

您可以通过多种方式配置您的实体。下面我将展示三种方式,一种使用 DataAnnotations,两种使用 Fluent Api.

第一个变体是使用 DataAnnotations。您可以使用属性 (DataAnnotations) 配置您的实体 classes 并且 properties.DataAnnotations 属性覆盖默认的 Code First 约定:

[Table(“BLOGS”)]
public class Blog
{
    [Key]
    [Column(“BLOGID”)]
    public int BlogId { get; set; }
    [Column(“NAME”)]
    public string Name { get; set; }
    [Column(“URL”)]
    public string Url { get; set; }

    public virtual List<Post> Posts { get; set; }
}
[Table(“POSTS”)]
public class Post
{
    [Key]
    [Column(“POSTID”)]
    public int PostId { get; set; }
    [Column(“TEXT”)]
    public string Text { get; set; }

    public int BlogId { get; set; }

    [ForeignKey("BlogId")]
    public virtual BaseCard Blog { get; set; }
}

然后,在您的上下文中 class,您无需重写 OnModelCreating 方法,EF 将使用该属性来映射您的实体和关系(它将创建一对多关系博客和 post):

public class BlogContext : DbContext
{
    public BlogContext(string name)
        : base(name)
    {
    }

    public IDbSet<Blog> Blogs { get; set; }
    public IDbSet<Post> Posts { get; set; }
}  

使用数据注释进行配置非常简单,它可能正是您正在寻找的。但是数据注释只允许您访问可能配置的一个子集(尽管比您目前看到的要多得多)。但是, Fluent API 使您可以访问更多内容,因此您可能更喜欢它。 使用 Fluent Api,您无需使用属性来映射实体 class 的字段和关系。 Fluent有两种使用方式Api:

1-在您的上下文中映射 OnModelCreating 方法中的实体(字段和关系)(您的第二个方法):

public class BloggingContext : DbContext
{     

    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>().ToTable("BLOGS");

        modelBuilder.Entity<Blog>().HasKey(t => t.BlogId);
        modelBuilder.Entity<Blog>().Property(t => t.BlogId).HasColumnName("BLOGID");
        modelBuilder.Entity<Blog>().Property(t => t.Name).HasColumnName("NAME");
        modelBuilder.Entity<Blog>().Property(t => t.Url).HasColumnName("URL");
       // The same with post

        //mapping one-to-many relationship
        modelBuilder.Entity<Post>().HasRequired(c => c.Blog)
       .WithMany(s => s.Posts)
       .HasForeignKey(c => c.BlogId);

}

2-使用 Fluent Api 的第二个变体是创建映射 classes(您的第一种方法)。这样,您可以在继承 EntityTypeConfiguration<TEntity>:

的 classes 中配置您的实体
public class BlogMap : EntityTypeConfiguration<Blog>
{
    public BlogMap()
    {
        ToTable("BLOGS");
        HasKey(t => t.BlogId);
        Property(t => t.BlogId).HasColumnName("BLOGID");
        Property(t => t.Name).HasColumnName("NAME");
        Property(t => t.Url).HasColumnName("URL");
    }

}

public class PostMap : EntityTypeConfiguration<Post>
{
    public PostMap()
    {
        ToTable("POSTS");
        HasKey(t => t.PostId);
        Property(t => t.Text).HasColumnName("TEXT");

      //mapping the relationship
        HasRequired(c => c.Blog)
        .WithMany(s => s.Posts)
        .HasForeignKey(c => c.BlogId);

    }
}

然后,要在上下文中包含映射,您需要将它们添加到 OnModelCreating 方法中:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Configurations.Add(new BlogMap());
  modelBuilder.Configurations.Add(new PostMap());
}

最好的配置方式是这样:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
      .Where(type => !String.IsNullOrEmpty(type.Namespace))
      .Where(type => type.BaseType != null && type.BaseType.IsGenericType
           && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
       foreach (var type in typesToRegister)
       {
           dynamic configurationInstance = Activator.CreateInstance(type);
           modelBuilder.Configurations.Add(configurationInstance);
       }
       base.OnModelCreating(modelBuilder);  
}

最后一个变体(第一种方法)对我来说是最好的,因为你不必触摸你的模型 classes(添加属性)来指定你想要的东西,如果你想要添加新实体或更改某些内容。

        string nspace = "CompanyAdministration.data.Models";
        var q = from t in Assembly.GetExecutingAssembly().GetTypes()
                where t.IsClass && t.Namespace == nspace && t.Name[0] != '<' && t.Name.Substring(0, 2) != "BOX" && t.Name != "CAContext"
                select t;
        foreach (Type t in q)
        {
                try
                {
                    MethodInfo method = modelBuilder.GetType().GetMethod("Entity");

                    method = method.MakeGenericMethod(new Type[] { t });

                    method.Invoke(modelBuilder, null);
                }
                catch
                {
                }
        }

        base.OnModelCreating(modelBuilder);