EntityFramework实体映射到数据库


 
在Entity Framework Code First与数据表之间的映射方式实现:

1、Fluent API映射

   通过重写DbContext上的OnModelCreating方法来访问Code First Fluent API

例如:

    public class BlogDbContext: DbContext
    {
        public BlogDbContext() : base("BlogDbContext") { }

        public DbSet<BlogUser> BlogUser{ get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<BlogUser>().HasKey(k => k.BlogUserId) //主键
                .Property(q => q.BlogName).IsRequired();//不能为空
        }
    }

 demo中的property方法用于为每个属于实体或复杂类型的属性配置特性。Property 方法用于获取给定属性的配置对象。配置对象上的选项特定于要配置的类型;例如,IsRequired表示不可为空。

  1. ToTable - TableAttribute:配置此实体类型映射到的表名
  2. HasColumnName - ColumnAttribute:配置用于存储属性的数据库列的名称
  3. HasForeignKey - ForeignKeyAttribute:将关系配置为使用在对象模型中的外键属性。如果未在对象模型中公开外键属性,则使用Map方法
  4. Ignore - NotMappedAttribute:从模型中排队某个属性,使该属性不会映射到数据库
  5. HasRequired:通过此实体类型配置必需关系。除非指定此关系,否则实体类型的实例将无法保存到数据库。数据库中的外键不可为null。
  6. HasOptional:从此实体类型配置可选关系。实体类型的实例将能保存到数据库,而无需指定此关系。数据库中的外键可为null。
  7. HasMany:从此实体类型配置一对多关系。
  8. WithOptional:将关系配置为required:optional。(required:0…1端的1,表示必需,不可为null;optional:0…1端的0,表示可选,可为null。下同)
  9. WithOptionalDependent:将关系配置为optional:optional。要配置的实体类型将成为依赖对象,且包含主体的外键。作为关系目标的实体类型将成为关系中的主体。
  10. WithOptionalPrincipal:将关系配置为optional:optional。要配置的实体类型将成为关系中的主体。作为关系目标的实体类型将成为依赖对象,且包含主体的外键。
  11. WithRequired:将关系的指定端配置为必需的,且在关系的另一端有导航属性。
  12. WithRequiredDependent:将关系配置为required:required。要配置的实体类型将成为依赖对象,且包含主体的外键。作为关系目标的实体类型将成为关系中的主体。
  13. WithRequiredPrincipal:将关系配置为required:required。要配置的实体类型将成为关系中的实体。作为关系目标的实体类型将成为依赖对象,且包含主体的外键。
  14. WillCascadeOnDelete:配置是否对关系启用级联删除。
  15. Map:将关系配置为使用未在对象模型中公开的外键属性。可通过指定配置操作来自定义列和表。如果指定了空的配置操作,则约定将生成列名。如果在对象模型中公开了外键属性,则使用 HasForeignKey 方法。并非所有关系都支持在对象模型中公开外键属性。
  16. MapKey:配置外键的列名。
  17. ToTable:配置外键列所在表的名称和架构

参考资料:https://msdn.microsoft.com/zh-cn/library/gg696117

如果这时候需要修改BlogUser这个实体,比如添加一个字段的时候直接运行就会报错,此时需要进行数据库更新迁移

建一个迁移类

using BlogDemo.Repositories;
using System;
using System.Collections.Generic;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Web;

namespace BlogDemo.Migrations
{
    public class Configuration:DbMigrationsConfiguration<BlogDbContext>
    {
        /// <summary>
        /// 初始化一个<see cref="MigrationsConfiguration"/>类型的新实例
        /// </summary>
        public Configuration()
        {
            //启用自动迁移
            AutomaticMigrationsEnabled = true;
            //获取或设置一个值表示如果在自动数据丢失是可以接受的 [慎重设置]
            AutomaticMigrationDataLossAllowed = true;
        } 
     }
}

同时也需要在Global.asax里面添加应用程序初始化的时候把数据库更新为最新的办法

        protected void Application_Start()
        {
            //数据库初始化为最新的版本
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogDbContext,Configuration>());
            AreaRegistration.RegisterAllAreas();

            // 默认情况下对 Entity Framework 使用 LocalDB
            //Database.DefaultConnectionFactory = new SqlConnectionFactory(@"Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True");

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

这个时候基本的操作可以实现,但是在实际的项目中数据表肯定不止一两张,几十张甚至上百张,如果按照这样的配置方法,需要配置映射关系的时候在 BlogDbContext的OnModelCreating进行配置,到后面在OnModelCreating方法中会添加很多关系

所以此时的解决方法就是新加一个映射类,在这个类中引用EntityTypeConfiguration,其实在BlogDbContext的OnModelCreating中有一句代码是modelBuilder.Entity<BlogUser>().HasKey(m => m.BlogUserId);   haskey转到定义可看到

所以在这里引用EntityTypeConfiguration是为了可以在构造方法中写配置,如下:

    public class BlogUserConfiguration : EntityTypeConfiguration<BlogUser>,IEntityMapper
    {
        public BlogUserConfiguration()
        {
            //设置主键
            HasKey(m => m.BlogUserId);
        }
    }

 

这样我们就可以不用在OnModelCreating中配置,可以把之前的代码删掉,用modelBuilder.Configurations.Add(new BlogUserConfiguration());

这样我们就用了这个通用的接口替换了OnModelCreating方法

BlogDbContext中的 public DbSet<BlogUser> BlogUser{ get; set; } 可以注释掉,然后直接用DbContext.Set<TEntity>()方法来实现指定实体的属性

如下:

   var dbContext = new BlogDbContext();
   IQueryable<BlogUser> blogUser= dbContext.Set<BlogUser>();
   blogUser.ToList();

 

 

2、Data Annotation验证

所引用程序集:System.ComponentModel.DataAnnotations

Data Annotation主要是在实体类的属性上加入需要验证的条件

例如:

StringLength表示字符长度限制50位,如果超过此长度则提示"输入过长,不能超过50位";

         [Required(ErrorMessage = "Name is required")]
         public string Name { get; set; }
  
         [Required(ErrorMessage = "Email is required")]
         [RegularExpression(@"^\s*([A-Za-z0-9_-]+(\.\w+)*@([\w-]+\.)+\w{2,3})\s*$", ErrorMessage = "Email is invalid")]
         public string Email { get; set; }
Required()表示这个属性是必填的,ErrorMessage的值是必填项没有填时,显示的错误提示信息
RegularExpression()是正则表达式验证,只有符合正则表达式的字符串才能通过验证


Fluent API和Data Annotation配置数据库映射参考博文
http://www.cnblogs.com/oppoic/p/ef_default_mapping_and_data_annotations_fluent_api.html