zoukankan      html  css  js  c++  java
  • EF6学习笔记三:全局约定和自定义约定,整理并记下来

    要专业系统地学习EF前往《你必须掌握的Entity Framework 6.x与Core 2.0》这本书的作者(汪鹏,Jeffcky)的博客:https://www.cnblogs.com/CreateMyself/    

    上一篇我简单弄了一下EF的简单配置,加上今天学的另外一些配置,我觉得得梳理一下。不要到处搞一点,得有个概念框架把这些东西归置好,不然容易乱。

    那我就把配置分为全局性的和局部的配置,也叫约定。

    全局当然就是我面向所有的模型进行统一的配置,局部的就是我针对某一个模型配置

    具体的配置,我们可以针对属性来:比如Person的Id属性我们设置它为主键、长度、数据类型……

                         可以针对类型来:比如Person的所有string类型的属性,我设置长度为200、非空……

    复杂类型约定

    像这种,如果EF检查Address里面没有Id属性就会认为是复杂类型。Student的构造函数里面对Address进行了初始化。这是因为复杂类型默认总是必需的

    这个体会不到可以先不管,等到后面用到这个,然后EF给你报错了再去体会也不迟。

    对于EF默认配置的态度是这样,即使它默认配置符合我的期望,我也会显示地去配置一下

    protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
            {
               //  显示配置复杂类型
                dbModelBuilder.ComplexType<Address>();
    }

    全局配置

    我想对表名进行一个全局设置,设置成tb_xxx这样样子,这样就是通过Types方法来

    复制代码
    // 全局配置,可以通过Types()配置表名
                dbModelBuilder.Types().Configure(x => x.ToTable(GetTableName(x.ClrType)));
    
    //  根据typeName,我进行拼接得到我想要的表名
    private string GetTableName(Type type)
            {
                //  用正则会好一些
                string[] arr = type.FullName.Split('.');
                return "tb_" + arr[arr.Length-1];
            }
    复制代码

    那我仅仅只是对单个model配置表名就这样弄

    dbModelBuilder.Entity<Student>().ToTable("tb_Students");

    我要对所有的表,设置属性名为“Name”的为主键

    modelBuilder.Properties().Where(x => x.Name == "Name").Configure(c => c.IsKey());

    我要对单张表,设置属性名为“Name”的为主键

    modelBuilder.Entity<Book>().HasKey(x => x.Name);

    现在我想所有model的string类型的属性设置大小为200

    modelBuilder.Properties<string>().Configure(x => x.HasMaxLength(200));

    现在来看一下int类型的主键,如果主键是int类型。FE映射后会自动设置为自增长,如果你要想主键是int类型,又不要它自增长

    modelBuilder.Entity<Book>().Property(x => x.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);

    设置Book类的Name属性非空

    modelBuilder.Entity<Book>().Property(x => x.Name).IsRequired();

    设置decimal类型,C#中decimal类型默认对应数据库中decimal[18,2],那我要保留四位小数

    modelBuilder.Entity<Book>().Property(x => x.Price).HasPrecision(18,4);

     还可以改变属性在数据库中的类型,比如我一个属性在C#中是DateTime类型,我要在数据库中用datetime2类型(数据库中默认是datetime)

    modelBuilder.Entity<Book>().Property(x => x.AddTime).HasColumnType("datetime2");

    总结一点C#中数据类型与数据库中类型的对比

    C#中 int(Int32) 类型默认映射后对应数据库中 int 类型

    C#中 long(Int64) 类型默认映射后对应数据库中 bigint 类型

    C#中 bool(Boolean) 类型默认映射后对应数据库中 bit 类型

    C#中 DateTime 类型默认映射后对应数据库中 datetime 类型

    C#中 float(Single) 类型默认映射后对应数据库中 real 类型

    C#中 double(Double) 类型默认映射后对应数据库中 float类型

    C#中 decimal(Decimal) 类型默认映射后对应数据库中 decimal[18,2]类型

    C#中 string(String) 类型默认映射后对应数据库中 nvarchar(MAX)类型

    自定义配置

    如果所有的配置都写在OnModelCreating()方法里面,那里面的代码是不是太多了啊,如果多人去修改这个方法内的内容,就容易冲突吧

    那么我们可以创建类,然后继承Convention,写到一边去

    复制代码
    //  我可以继承自Convention单独弄出文件来写配置
        public class CustomKeyConvention:Convention
        {
            public CustomKeyConvention()
            {
                Properties().Where(x => x.Name == "Id").Configure(c => c.IsKey());
            }
        }
    复制代码

    然后再OnModelCreating()方法中添加配置

    //  自定义配置
                dbModelBuilder.Conventions.Add<CustomKeyConvention>();

    这还是会对OnModelCreating()进行修改,那么我们可以通过反射,找到这些配置文件,然后再弄个循环,就行了

    复制代码
    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);
                    dbModelBuilder.Configurations.Add(configurationInstance);
                }
                base.OnModelCreating(dbModelBuilder);
    复制代码

     2019年1月12日15:30:13 改正:全局配置,可以创建一个类,继承自Convention,然后在OnModelCreationg中进行添加,这里的反射视乎对个全局的配置弄不了,我没有弄出来。

    作者的书上是关系的配置,不是全局配置。所以我这里不能这样做

     
  • 相关阅读:
    codeforces 455B A Lot of Games(博弈,字典树)
    HDU 4825 Xor Sum(二进制的字典树,数组模拟)
    hdu 1800 Flying to the Mars(简单模拟,string,字符串)
    codeforces 425A Sereja and Swaps(模拟,vector,枚举区间)
    codeforces 425B Sereja and Table(状态压缩,也可以数组模拟)
    HDU 4148 Length of S(n)(字符串)
    codeforces 439D Devu and Partitioning of the Array(有深度的模拟)
    浅谈sass
    京东楼层案例思维逻辑分析
    浅谈localStorage和sessionStorage
  • 原文地址:https://www.cnblogs.com/anyihen/p/12818358.html
Copyright © 2011-2022 走看看