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中进行添加,这里的反射视乎对个全局的配置弄不了,我没有弄出来。

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

     
  • 相关阅读:
    nyoj999 师傅又被妖怪抓走了 (预处理+bfs+状态压缩)
    使用逆波兰式进行表达式求值
    [moses笔记]编译含有nplm的moses解码器
    菲波那契数列编程实现
    引领网页设计潮流的优秀网页作品赏析
    MFC中获取各个窗口之间的句柄或者指针对象的方法
    UVALive 6529 Eleven 区间dp
    jquery 实现菜单的下拉菜单
    数字图像和视频处理的基础-第4周运动预计matlab练习题
    setjmp与longjmp
  • 原文地址:https://www.cnblogs.com/anyihen/p/12818358.html
Copyright © 2011-2022 走看看