zoukankan      html  css  js  c++  java
  • EF实体框架之CodeFirst五

    上一博客学习了下基本的约定配置,留下几个遗漏的,这篇就是学习下遗漏一复杂类型。

    一、什么是复杂类型?

    书中说道:“复杂类型也可视作值类型(?)可以作为附加属性添加到其他类。复杂类型与实体类型的区别在于复杂类型没有其自己的键。它是依赖于其"宿主"类型跟踪变化 和持久化。一个没有Key属性的类型,并且作为属性映射到一个或多个类型中,Code First就会将其视作为复杂类型。Code First将预设复杂类型的属性出现在宿主类型映射到数据库的表中。”

    说简单一点就是,项目中有个类A,这个A,会被其他类引用到比如:实体类B 和 实体类C,但是建立数据库的时候,我们不想为这个分割类A建立表,而是把A类中的属性等建立到 B 和 C 映射的表中,这时候,我们管 A 叫做复杂类型。

    二、复杂类型和实体类型的区别

    首先还是定义两个类Person类和IDCard类还有数据库上下文。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Data.Entity;
    using EFCodeFirstModels;
    using System.Configuration;
    
    
    namespace EFCodeFirstDataAccess
    {
        public class EFCodeFirstDbContext:DbContext
        {
    
            public EFCodeFirstDbContext() : base("MyStrConn")
            {
            }
            public DbSet<Person> Persons { get; set; }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace EFCodeFirstModels
    {
        public enum SexType { Male, Female }
    
        [Table("Person")]
        public class Person
        {
            [Key]
            public string PersonId { get; set; }
            //姓名
          
            public string Name { get; set; }
            //性别
            public SexType Sex { get; set; }
            //年龄
            public int Age { get; set; }
    
            public IDCard Card { get; set; }
    
    
            public Person(string personId, string name, SexType sex, int age,IDCard card)
            {
                PersonId = personId;
                Name = name;
                Sex = sex;
                Age = age;
                Card = card;
             
            }
            public Person() { }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace EFCodeFirstModels
    {
        
        public class IDCard
        {
            //法定出生日期
            public DateTime BirthDate { get; set; }
    
        }
    }

    在上面的IDCard中并没有主键,这个是需要留意的,然后呢新增一个Person对象在数据库上下文中。

                using (var db=new EFCodeFirstDbContext())
                {
                    IDCard card = new IDCard();
                    card.BirthDate = DateTime.Now;
                    Person p = new Person("0001","cuiyanwei",SexType.Female,25,card);
                    db.Persons.Add(p);
                    db.SaveChanges();
                    Console.WriteLine("Scueess");
                }

    此时会生成下面的表结构。

    上面可以看到Person表中增加了一个Card_BirthDate列,但是如果在IDCard类中增加一个主键,结果就会不一样。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace EFCodeFirstModels
    {
        
        public class IDCard
        {
            [Key]
            public int CardId { get; set; }
            //法定出生日期
            public DateTime BirthDate { get; set; }
    
        }
    }

    可以看到,数据库中多生成了一个表。Person表中增加了一个外键Card_CardId.

    三、复杂类型嵌套

    看到这你可能会问这也没提到复杂类型几个字啊,哪来的复杂类型了。上面的例子中IDCard虽然也是复杂类型,由于IDCard类中属性比较简单,没有嵌套这其他的类,所以EF就默认映射到Person表中了,但是假如IDCard类中有其他的类,属于类型嵌套的话那就麻烦了。首先看下如果有嵌套不指定会怎么样?

    可以在IDCard类中增加一个属性,用来表示出生地方的经纬度(做个比喻,不可能人出生在一个经纬度的点上,也是大致的位置)。经纬度用Location类表示。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace EFCodeFirstModels
    {
        //[ComplexType]
        public class Location
        {
            //经度
            public double Longitude { get; set; }
    
            //纬度
            public double Latitude { get; set; }
    
        }
    }
        public class IDCard
        {
    
            //法定出生日期
            public DateTime BirthDate { get; set; }
    
            //出生地的位置 经纬度
            public Location BirthPlace { get; set; }
    
        }

    同样新增一个Person对象,此时就会报下面的错误。

    这是为什么呢?因为系统识别不了IDCard类是复杂类型。那怎么解决呢,很简单。只需指定IDCard是复杂类型就ok了。

        [ComplexType]
        public class IDCard

    而在Location类上并没有指定复杂类型,这也将Location类认为是复杂类型。

  • 相关阅读:
    支持高速局域网文件传输的企业云盘(速度可达20M)
    高版本Sqlserver数据库还原到低版本数据库的实现方式
    sqlserver没有采用默认实例时 通过ip进行链接
    AM8互联设置方法
    蛮好用的Gungho重点工作督查督办跟踪管理系统
    AM8后台历史数据手工清理方法
    AM8不能下任何载附件及所有聊天记录无法登记
    【OI】时间复杂度
    【OI】矩阵快速幂
    【Ubuntu】奇怪的无法启动
  • 原文地址:https://www.cnblogs.com/5ishare/p/5836626.html
Copyright © 2011-2022 走看看