• Learning EntityFramework(5)


    复合类型(Complex types)

    复合类型(Complex Types)跟Entity类型的区别在于,复合类型(Complex Types)没有Key。复合类型跟踪改变和存储是要依赖宿主类型的。

    从代码来看就更直观。

    首先,假设我们有一个Person类,这个类包含了SSN,FirstName,LastName和Address的信息。代码如下

    public class Person
    {
        public int PersonId { get; set; }
        public int SocialSecurityNumber { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string StreetAddress { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }
    }

    但是根据设计模式或为了能够练习更好的编程习惯,我们会单独抽象出一个Address类,来存储Address的信息。

    public class Address
    {
        public int AddressId { get; set; }
        public string StreetAddress { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }
    }
    public class Person
    {
        public int PersonId { get; set; }
        public int SocialSecurityNumber { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Address Address { get; set; }
    }

    如果通过上面的两个类,Code Fist将在数据库中生成两张表,而这又不是我们想要的结果。在数据库层面我们只是想有一张表,而在代码层面,我们希望可以有单独的Address类来存储Address信息。这时候,我们希望把Address定义为一个复合类型,而不是entity类型。

    要如何做才能把Address类变成复合类型呢?复合类型和entity类型的区别在于,复合类型没有key。所以,我们只需要把AddressId从Address类中去掉就可以了。

    在做插入操作时,出现来另外一个问题,在Person类中的Address如果为NULL时,当调用SaveChanges方法时将会抛出一个DbUpdateException。解决方法也很简单,在Person类的构造函数中,实例化一个Address的实例赋值给Address属性。

    另外两个规则应用于复合类型。其一,复合类型只能包含原始(primitive)数据类型;其二,当被其他类使用时,不能是集合类型。换言之,如果Person类中的是一个List<Address>或者另外一个集合类型存在于Address类中,Address将不被视为复合类型。

    如果你一定要使用AddressId时,可以通过DataAnnotation,使用[ComplexType]修饰Address类。Fluent API实现方式: modelBuilder.ComplexType<Address>();

    让我们来看一个更复杂的复合类型的例子

    public class PersonalInfo
    {
        public Measurement Weight { get; set; }
        public Measurement Height { get; set; }
        public string DietryRestrictions { get; set; }
    }
    public class Measurement
    {
        public decimal Reading { get; set; }
        public string Units { get; set; }
    }

    我想让PersonalInfo和Measurement都是复合类型。两个类都没有Key,同样在Person类的构造函数里面也将这两个类型实例化并赋值到对应的属性上。但在运行时依旧会报错。因为PersonalInfo并没有完全满足复合类型的条件——使用原始数据类型。只需要在PersonalInfo类型上面加上[ComplexType]的修饰,就能够使代码正常工作了。
    同样的,DataAnnotation和FluentAPI都可以对复合类型里面的属性进行配置。

  • 相关阅读:
    Hibernate的注释该如何使用?每一个注释代表什么意思?
    J2SE总结(一)-------容器
    解决hibernate向mysql插入中文乱码问题(更改MySQL字符集)
    android程序员成长路径的思考
    Fragment总结
    onCreateView的一个细节--Fragment
    屏幕适配
    表驱动法3
    表驱动法2
    表驱动法1
  • 原文地址:https://www.cnblogs.com/OliverZh/p/ef5.html
Copyright © 2020-2023  润新知