<th id="v9g6b"><track id="v9g6b"></track></th>

  • <em id="v9g6b"><acronym id="v9g6b"></acronym></em>
    <progress id="v9g6b"><pre id="v9g6b"></pre></progress>
    <tbody id="v9g6b"></tbody>
    <button id="v9g6b"><acronym id="v9g6b"></acronym></button>
    <rp id="v9g6b"><ruby id="v9g6b"></ruby></rp>

        <dd id="v9g6b"></dd>

        <em id="v9g6b"></em>

          深入MVC框架--EF中的导航属性优势与弊端(二)

          上一篇中我们解决了因为EF导航属性使用不当出现的问题,其实归根揭底是我们没有配置Model映射关系导致的,即 Fluent API使用EntityTypeConfiguration来配置ORM映射。
          Fluent API
          实现
          总结
          利与弊
          Fluent API

          Fluent API功能非常强大,它在通过重写DbContext上的OnModelCreating方法来实现自定义规则,可以设置主键、组合主键、外键、指定长度、指定属性是否映射到表等等。
          创建EntityTypeConfiguration ORM映射。
          在OnModelCreating方法下使用,通过反射动态加入。
          在上一篇的问题1问题描述,我们也可以通过Fluent API来解决。

          实现

          创建EntityTypeConfiguration ORM映射。

              public class DepartmentMapper : EntityTypeConfiguration<Department>
              {
                  public DepartmentMapper()
                  {
                      HasKey(t => t.DepartmentID);
                      this.Property(t => t.DepartmentName).IsRequired().HasMaxLength(200);
                  }
              }
              public class SystemRoleMapper : EntityTypeConfiguration<SystemRole>
              {
                  public SystemRoleMapper()
                  {
                      this.HasKey(t => t.RoleID);
                      this.Property(t => t.RoleName).IsRequired().HasMaxLength(200);
                      this.Property(t => t.DepartmentID).IsOptional();
                      this.Ignore(t => t.DepartmentName);
                      this.Ignore(t => t.Functions);
                  }
              }
              public class SystemFunctionMapper : EntityTypeConfiguration<SystemFunction>
              {
                  public SystemFunctionMapper()
                  {
                      this.HasKey(t => t.FunctionID);
                      this.Property(t => t.FunctionCode).IsRequired().HasMaxLength(50);
                      this.Property(t => t.FunctionName).IsRequired().HasMaxLength(200);
                  }
              }
              public class SystemRoleFunctionMapper : EntityTypeConfiguration<SystemRoleFunction>
              {
                  public SystemRoleFunctionMapper()
                  {
                      this.HasKey(t => new { t.RoleID, t.FunctionID });
                      this.HasRequired(t => t.Function).WithMany().HasForeignKey(t => t.FunctionID);
                      this.HasRequired(t => t.Role).WithMany().HasForeignKey(t => t.RoleID);
                  }
              }
          
          
          通过重写DbContext上的OnModelCreating方法来实现自定义规则。
          /// <summary>
          /// 重载 DbContext.OnModelCreating 方法,添加当前程序集中的所有 EntityTypeConfiguration&lt;&gt;
          /// 的Map映射程序实现到DbModelBuilder中。 
          /// </summary>
          /// <param name="modelBuilder"></param>
          protected override void OnModelCreating(DbModelBuilder modelBuilder)
          {                        
              modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
              modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
              // dynamically load all configuration
              // System.Type configType = typeof(LanguageMap);
              // any of your configuration classes here
              // var typesToRegister = Assembly.GetAssembly(configType).GetTypes()
              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);
              }
              // ...or do it manually below. For example,
              // modelBuilder.Configurations.Add(new LanguageMap());
              base.OnModelCreating(modelBuilder);
          }
          
          

          总结

          上述OnModelCreating方法我们通过反射自动添加的Model映射配置(EntityTypeConfiguration类型),在EntityTypeConfiguration配置中我们可以设置如下属性和方法:

          • 设置主键 modelBuilder.Entity<x>().HasKey(t => t.Id);
          • 设置联合主键 modelBuilder.Entity<x>().HasKey(t =>new{t.Code,t.Id} );
          • 取消数据库字段标识(取消自动增长) modelBuilder.Entity<x>().Property(t=>t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
          • 设置数据库字段标识(自动增长) modelBuilder.Entity<SystemOrder>().Property(t =>t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
          • 设置字段最大长度 modelBuilder.Entity<Model_1>().Property(t => t.Name).HasMaxLength(100);
          • 设置字段为必需 modelBuilder.Entity<Model_1>().Property(t =>t.Id).IsRequired();
          • 属性不映射到数据库 modelBuilder.Entity<Model_1>().Ignore(t => t.A);
          • 将属性指定数据库列名: modelBuilder.Entity<Model_1>().Property(t => t.A) .HasColumnName("A_C1");
          • 级联删除课程与学生(数据库默认是不级联删除的) modelBuilder.Entity<Course>().HasRequired(t => t.Student).WithMany(t => t.Student).HasForeignKey(d => d.StudentID).WillCascadeOnDelete();
          • 设置为Timestamp modelBuilder.Entity<Course>() .Property(t => t.Timestamp) .IsRowVersion();
          • 表1对0..1(Course实体可以包含零个或一个Level) modelBuilder.Entity<Level>().HasRequired(t => t.Course).WithOptional(t => t.Level);
          • 表1对1 modelBuilder.Entity<Model_1>().HasRequired(t => t.Model_2).WithRequiredPrincipal(t => tModel_1);
          • 表1对n(Department为主表,一个部门有多个角色) modelBuilder.Entity<SystemRole>().HasRequired(c => c.Department) .WithMany(t => t.SystemRole)
          • 指定外键名(指定表Student中的字段CourseID为外键) modelBuilder.Entity<Course>().HasRequired(c => c.Student).WithMany(t => t.Course).Map(m => m.MapKey("CourseID"));
          • 表n对n,关联表SystemRoleFunction this.HasKey(t => new { t.RoleID, t.FunctionID }); this.HasRequired(t => t.Function).WithMany().HasForeignKey(t => t.FunctionID); this.HasRequired(t => t.Role).WithMany().HasForeignKey(t => t.RoleID);
          利与弊

          这种方法好处是不言而喻的,除了ORM本身的好处外,我们通过该方法做好了模型与模型、表与表之间的关系,在后续开发直接获取他们的数据就可以,就不用担心他们的关系问题。
          但是它有一个明显的缺点,就是我们不能直接去动一丝一毫的数据库表结构,动了就会导致EF数据迁移记录和数据库对不上,导致出错(详细见参考文章 深入Web框架-EF数据迁移常见问题)。
          更加让人难以接受的是在删除N对N关系的数据表时,必须用控制台来删除,这个对不能深入理解EF机制的同学来说是致命的,这无疑大大增加了项目数据链路层的复杂性,所以我们决定在 软件开发框架中舍弃了Fluent API这一做法,通过DbSet显示将模型添加到DbContext中。

          网站&系统开发技术学习交流群:463167176

          本站文章除注明转载外,均为本站原创或翻译,欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,共创和谐网络环境。
          转载请注明:文章转载自:华晨软件-云微开发平台 ? 深入MVC框架--EF中的导航属性优势与弊端(二)
          本文标题:深入MVC框架--EF中的导航属性优势与弊端(二)
          本文地址:http://www.sajuice.com/OrgTec/DB/0004.html

          相关文章: 深入Web框架-EF数据迁移常见问题 | .Net MVC中config怎么配置mysql

          电话
          电话 18718672256

          扫一扫
          二维码
          本港台开奖 <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>