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");
                        });
                }
    复制代码

    生成表结构

  • 相关阅读:
    2020.10.23 19级training 补题报告
    2020.10.17 天梯赛练习 补题报告
    2020.10.16 19级training 补题报告
    2020.10.9 19级training 补题报告
    2020.10.10 天梯赛练习 补题报告
    2020.10.3 天梯赛练习 补题报告
    2020.10.2 19级training 补题报告
    第十届山东省ACM省赛复现补题报告
    VVDI Key Tool Plus Adds VW Passat 2015 Key via OBD
    Xhorse VVDI Prog Software V5.0.3 Adds Many MCUs
  • 原文地址:https://www.cnblogs.com/yeagen/p/12692651.html
Copyright © 2011-2022 走看看