zoukankan      html  css  js  c++  java
  • Entity Framework、 代码优先,TPH、TPT、TPC与继承类

     三者区别
    EF默认:TPH
    TPH:基类和子类在一张表里,以Discriminator自动区别不同的类,Discriminator名称和值可在FlushApi中修改
    modelBuilder.Entity<Dog>().Map<WhiteDog>(m => m.Requires("DogType").HasValue(1)).Map<BlackDog>(m => m.Requires("DogType").HasValue(2));

    TPT:基类和子类在不同的表里,子类表中,没有基类的属性,以外键相连

    TPC:基类没有单独的表,每个子类一张表,每个子类表中都含有基类的属性
     
    如何实现:
    TPH:默认,不自定义表名
    TPT:ToTable(给哪个子类ToTable,哪个子类就单独表,其他的还在一张表里)
    modelBuilder.Entity<Dog>().HasKey(e => e.Id).Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    //如果某个子类不写表名,则它会和基类表放在一起,其他写表名的子类依然会分开
    modelBuilder.Entity<WhiteDog>().Map(m => { m.ToTable("WhiteDog"); });
    modelBuilder.Entity<BlackDog>().Map(m => { m.ToTable("BlackDog"); });
    modelBuilder.Entity<RedDog>().Map(m => { m.ToTable("RedDog"); });

    TPC:ToTable + MapInheritedProperties(); + 基类为抽象类

    TPC备注:
    如果三张表里的Id一样的话,读取基类时会报主键相同的错误,如果是用Guid当主键就可以解决
    如果不需要从总表读取统一读取,还不如把基类设置为抽象类,三个子类正常建就行了
    TPC抽象类很重要,如果不是抽象类就变为TPT
    如果一个子类调用了MapInheritedProperties,那么就要全部子类都要调用MapInheritedProperties,否则系统报错。
    如果只调用MapInheritedProperties,不定义表名,则变为TPH
    modelBuilder.Entity<Dog>().HasKey(e => e.Id);//TPC模式建议大家用Guid做为主键,如果是自增长主键,主键相同时,读取所有类的话,系统会报错
    modelBuilder.Entity<WhiteDog>().Map(m => { m.MapInheritedProperties(); m.ToTable("WhiteDog"); });
    modelBuilder.Entity<BlackDog>().Map(m => { m.MapInheritedProperties(); m.ToTable("BlackDog"); });
    modelBuilder.Entity<RedDog>().Map(m => { m.MapInheritedProperties(); m.ToTable("RedDog"); });

     如何使用:

    无论哪种模式,EF的读取方式是一样的

    读取所有子类:

     var dogs = db.Dogs.Where(a => a.Id == 1).FirstOrDefault();

    读取某个子类:

    var dogs = db.Dogs.OfType<RedDog>().Where(a => a.Id == 1).FirstOrDefault();

    读取多个子类:

    var dogs = db.Dogs.Where(a => (a is BlackDog) || (a is RedDog)).ToList();
     

    注意:如果OfType或is判断里的类型不是Dogs的本身或子类,则会报以下错误

    DbOfTypeExpression requires an expression argument with a polymorphic result type that is compatible with the type argument.
     
     
     

    每个类型一张表【TPT】

    声明方式

    复制代码
       public class Business
        {
            [Key]
            public int BusinessId { get; protected set; }
            public string Name { get; set; }
            public string LicenseNumber { get; set; }
        }
        public class Retail : Business
        {
            public string Address { get; set; }
            public string City { get; set; }
            public string State { get; set; }
            public string ZIPCode { get; set; }
        }    
        public class eCommerce : Business
        {
            public string URL { get; set; }
        }public class BusinessesContext : DbContext
        {
            public DbSet<Business> Businesses { get; set; }
           
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Entity<Business>()
                    .Property(b=>b.BusinessId)
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
                modelBuilder.Entity<Business>().ToTable("Business", "halower");
                modelBuilder.Entity<Retail>().ToTable("Retail", "halower");
                modelBuilder.Entity<eCommerce>().ToTable("eCommerce", "halower");
            }
        }
    复制代码

    怎么使用

    复制代码
     private static void Main(string[] args)
            {
                using (var context = new BusinessesContext())
                {
                     
                    var retail = new Retail
                    {
                        Name = "Shop and Save",
                        LicenseNumber = "200C",
                        Address = "101 Main",
                        City = "Anytown",
                        State = "TX",
                        ZIPCode = "76106"
                    };
                    context.Businesses.Add(retail);
                    var web = new eCommerce
                    {
                        Name = "BuyNow.com",
                        LicenseNumber = "300AB",
                        URL = "www.buynow.com"
                    };
                    context.Businesses.Add(web);
                    context.SaveChanges();
                }
                using (var context = new BusinessesContext())
                {
                    Console.WriteLine("
    --- All Businesses ---");
                    foreach (var b in context.Businesses)
                    {
                        Console.WriteLine("{0} (#{1})", b.Name, b.LicenseNumber);
                    }
                    Console.WriteLine("
    --- Retail Businesses ---");
                    //OfType<T>:根据指定类型筛选
                    foreach (var r in context.Businesses.OfType<Retail>())
                    {
                        Console.WriteLine("{0} (#{1})", r.Name, r.LicenseNumber);
                        Console.WriteLine("{0}", r.Address);
                        Console.WriteLine("{0}, {1} {2}", r.City, r.State, r.ZIPCode);
                    }
                    Console.WriteLine("
    --- eCommerce Businesses ---");
                    foreach (var e in context.Businesses.OfType<eCommerce>())
                    {
                        Console.WriteLine("{0} (#{1})", e.Name, e.LicenseNumber);
                        Console.WriteLine("Online address is: {0}", e.URL);
                    }
                    Console.ReadKey();
                }
            }
    复制代码

    生成表结构

    运行效果

    每个继承层次一张表【TPH】

    声明方式

    复制代码
      public abstract class Employee
            {
                public int EmployeeId { get; protected set; }
                public string FirstName { get; set; }
                public string LastName { get; set; }
            }
    
            public class FullTimeEmployee : Employee
            {
                public decimal? Salary { get; set; }
            }
    
            public class HourlyEmployee : Employee
            {
                public decimal? Wage { get; set; }
            }
    
            public class EmployeeContext: DbContext
            {
                public DbSet<Employee> Employees { get; set; }
    
                protected override void OnModelCreating(DbModelBuilder modelBuilder)
                {
                    base.OnModelCreating(modelBuilder);
                    modelBuilder.Entity<Employee>()
                        .HasKey(e => e.EmployeeId)
                        .Property(e => e.EmployeeId)
                        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
                    modelBuilder.Entity<Employee>()
                        .Map<FullTimeEmployee>(m => m.Requires("EmployeeType").HasValue(1))
                        .Map<HourlyEmployee>(m => m.Requires("EmployeeType").HasValue(2));
                }
    复制代码

    怎么使用

    复制代码
          private static void Main(string[] args)
            {
                using (var context = new EmployeeContext())
                {
                    var fte = new FullTimeEmployee
                    {
                        FirstName = "Jane",
                        LastName = "Doe",
                        Salary = 71500M
                    };
                    context.Employees.Add(fte);
                    fte = new FullTimeEmployee
                    {
                        FirstName = "John",
                        LastName = "Smith",
                        Salary = 62500M
                    };
                    context.Employees.Add(fte);
                    var hourly = new HourlyEmployee
                    {
                        FirstName = "Tom",
                        LastName = "Jones",
                        Wage = 8.75M
                    };
                    context.Employees.Add(hourly);
                    context.SaveChanges();
                }
                using (var context = new EmployeeContext())
                {
                    Console.WriteLine("--- All Employees ---");
                    foreach (var emp in context.Employees)
                    {
                        bool fullTime = !(emp is HourlyEmployee);
                        Console.WriteLine("{0} {1} ({2})", emp.FirstName, emp.LastName,
                            fullTime ? "Full Time" : "Hourly");
                    }
                    Console.WriteLine("--- Full Time ---");
                    foreach (var fte in context.Employees.OfType<FullTimeEmployee>())
                    {
                        Console.WriteLine("{0} {1}", fte.FirstName, fte.LastName);
                    }
                    Console.WriteLine("--- Hourly ---");
                    foreach (var hourly in context.Employees.OfType<HourlyEmployee>())
                    {
                        Console.WriteLine("{0} {1}", hourly.FirstName, hourly.LastName);
    
                    }
                }
                Console.ReadKey();
            }
    复制代码

    生成表结构

    运行效果

     每个子类一张表【TPC】

    声明方式

    复制代码
     protected override void OnModelCreating(DbModelBuilder modelBuilder)
                {
                    base.OnModelCreating(modelBuilder);
                    modelBuilder.Entity<Employee>()
                        .HasKey(e => e.EmployeeId)
                        .Property(e => e.EmployeeId)
                        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
                    modelBuilder.Entity<FullTimeEmployee>()
                        .Map(m =>
                        {
                            m.MapInheritedProperties();
                            m.ToTable("FullTimeEmployee");
                        });
                    modelBuilder.Entity<HourlyEmployee>()
                        .Map(m =>
                        {
                            m.MapInheritedProperties();
                            m.ToTable("HourlyEmployee");
                        });
                }
    复制代码

    生成表结构

  • 相关阅读:
    Linux top详解
    Could not load file or assembly 'Microsoft.Extensions.Hosting.Abstractions, Version=3.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.
    面试官最爱的 volatile 关键字,这些问题你都搞懂了没?
    HashMap面试题及答案(2020版)
    Linux 下安装Rider 和 Net core SDK
    [Dnc.Api.Throttle] 适用于. Net Core WebApi 接口限流框架
    开启谷歌浏览器多线程下载
    Ubuntu 20.04 安装 向日葵远程
    java
    docker镜像处理命令格式化工具 docker-command-format.html
  • 原文地址:https://www.cnblogs.com/yeagen/p/12692651.html
Copyright © 2011-2022 走看看