• Programming Entity Framework CodeFirst--表关系约定


        表之间的关系分为一对多,多对多,一对一三种,实质就是对外键进行配置。

        一、一对多

        1. Required

            Destination包含Lodging>的集合。

    public class Destination
    {
    public int DestinationId { get; set; }
    public string Name { get; set; }
    public string Country { get; set; }
    public string Description { get; set; }
    public byte[] Photo { get; set; }
    public List<Lodging> Lodgings { get; set; }
    }
    public class Lodging
    {
    public int LodgingId { get; set; }
    public string Name { get; set; }
    public string Owner { get; set; }
    public bool IsResort { get; set; }
    public decimal MilesFromNearestAirport { get; set; }
    public Destination Destination { get; set; }
    }
    View Code

      这样,EF会自动给Lodging表生成外键。Destination_LodgingId.

      

      注意到这个时候Fk,是可以为Null的。修改Lodging,给Destination加上Required。

    [Required]
    public Destination Destination { get; set; }

    再运行

     注意到Fk是not null了。

     用Api的方式:

    modelBuilder.Entity<Destination>().HasMany(d => d.Lodgings).WithOptional(l => l.Destination);

    在配置表关系的时候,has方法多是和With方法一起搭配使用。

    • HasOptional  //可为null
    • HasRequired  //不为null
    • HasMany  //集合 

    has表示主体对从体的关系。.HasMany(d => d.Lodgings) 表示Destination拥有Lodgings的集合。

    • WithOptional //可为null
    • WithRequired //不可为null
    • WithMany //集合

    with表示从体对主体。.WithOptional(l => l.Destination); 表示Lodging的Destination是可以为null的。

    可以给Lodging加一个外键。

     public int DestinationId { get; set; }

    有了外键,我们赋值的时候附一个id就行了,而不用赋一个对象。

     

    外键DestinationId为非null,是因为他是int型的,如果换成Nullable<int>,数据库会将其设置为可null。

    2.Foreignkey

        有时候我们属性命名并不规范,如下。这个时候EF就不知道AccommodationId是我们指定的外键如果没有特性[Foreignkey("name")]

    [ForeignKey("Accommodation")]
    public int AccommodationId { get; set; }
    public Lodging Accommodation { get; set; }
    //.....或.....
    public int AccommodationId { get; set; }
    [ForeignKey("AccommodationId")]
    public Lodging Accommodation { get; set; }

    API:

    modelBuilder.Entity<InternetSpecial>().HasRequired(s => s.Accommodation).WithMany(l => l.InternetSpecials)

    同样在2中,我们删掉Lodging中的Destination和DestinationId,加上LocationId。 

        // public Destination Destination { get; set; }
           // public int DestinationId { get; set; }
            public int LocationId { get; set; }

    要指定LocationId为外键可以:

     修改Destination

    [ForeignKey("LocationId")]
    public List<Lodging> Lodgings { get; set; }

    Api:

    modelBuilder.Entity<Destination>().HasMany(d => d.Lodgings).WithRequired().HasForeignKey(l => l.LocationId);

    3.InverseProperty

    再复杂些,Person类拥有两个Lodging集合。

     public class Person
        {
            public Person()
            {
                Address=new Address();
                Info=new PersonalInfo()
                {
                    Weight = new Measurement(),
                    Height = new Measurement()
                };
            }
    
            [Key]
            public int SocialSecurityNumber { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            [Timestamp]
            public byte[] RowVersion { get; set; }
            public PersonalInfo Info { get; set; }
            public Address Address { get; set; }
            public PersonPhoto Photo { get; set; }
            public List<Lodging> PrimaryContactFor { get; set; }
            public List<Lodging> SecondaryContactFor { get; set; }
        }
    public class Lodging
        {
            public int LodgingId { get; set; }
            [Required]
            [MaxLength(200)]
            [MinLength(10)]
            public string Name { get; set; }
            [StringLength(200, MinimumLength = 2)]
            public string Owner { get; set; }
            public bool IsResort { get; set; }
           // public Destination Destination { get; set; }
           // public int DestinationId { get; set; }
            public List<InternetSpecial> InternetSpecials { get; set; }
             public Person PrimaryContact { get; set; }
             public Person SecondaryContact { get; set; }
    
        }
    View Code

    这个时候直接生产的表是:

    这样就乱掉了。EF搞不清。需用用InverseProperty告诉它

    [InverseProperty("PrimaryContactFor")]
    public Person PrimaryContact { get; set; }
    [InverseProperty("SecondaryContactFor")]
    public Person SecondaryContact { get; set; }

    然后生成的外键就干净了。(SocialSecurityNumber是person的主键)

    4.级联删除。

       在数据库中,因为外键会在实体删除的时候触发级联删除。我们有时候需要配置这个功能关闭。且只有API的方式配置

    HasRequired(l=>l.Destination).WithMany(d=>d.Lodgings).WillCascadeOnDelete(false)

     如果有多个Required指向同一张表,有的数据库是不支持多个关系的级联删除,这个时候也需要关闭这个功能。

    二、多对多

       1.Trip和Activity相互包含彼此的集合。

     public class Trip
        {
            [Key]
            public Guid Identifier { get; set; }
            public DateTime StartDate { get; set; }
            public DateTime EndDate { get; set; }
            public decimal CostUSD { get; set; }
            [Timestamp]
            public byte[] RowVersion { get; set; }
            public decimal MilesFromNearestAirport { get; set; }
    
            public List<Activity> Activities { get; set; }
        }
        public class Activity
        {
            public int ActivityId { get; set; }
            [Required, MaxLength(50)]
            public string Name { get; set; }
            public List<Trip> Trips { get; set; }
        }

    生成了三张表:

    可以再修改第三张表的表名。TripConfiguration:

    HasMany(t => t.Activities).WithMany(a => a.Trips).Map(c => c.ToTable("TripActivities"));

    进而也可以修改这个表的键

    HasMany(t => t.Activities)
    .WithMany(a => a.Trips)
    .Map(c =>
    {
    c.ToTable("TripActivities");
    c.MapLeftKey("TripIdentifier");
    c.MapRightKey("ActivityId");
    });

      

    进行一个查询:

    var tripWithActivities = context.Trips.Include("Activities").FirstOrDefault();

    三、一对一

     如果两个对象,单独相互依赖,这个时候就需要指定谁依赖谁。不然EF不知道就会报错。比如PersonPhoto和Person是一对一的关系。

      public class Person
        {
            public Person()
            {
                Address=new Address();
                Info=new PersonalInfo()
                {
                    Weight = new Measurement(),
                    Height = new Measurement()
                };
            }
    
            [Key]
            public int SocialSecurityNumber { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            [Timestamp]
            public byte[] RowVersion { get; set; }
            public PersonalInfo Info { get; set; }
            public Address Address { get; set; }
            public PersonPhoto Photo { get; set; }
            public List<Lodging> PrimaryContactFor { get; set; }
            public List<Lodging> SecondaryContactFor { get; set; }
        }
        public class PersonPhoto
        {
            [Key]
            [ForeignKey("PhotoOf")]
            public int PersonId { get; set; }
            public byte[] Photo { get; set; }
            public string Caption { get; set; }
            public Person PhotoOf { get; set; }
        }
    View Code

    没有[Required]不然会出现下面的错误,EF它不能擅自决定。

     

     以上都是这一章的笔记。

     园友的同类型博客

    http://www.cnblogs.com/libingql/p/3353112.html

  • 相关阅读:
    pro asp.net mvc5 7
    pro asp.net mvc5
    第九章 观察者模式 OBSERVER
    第八章 单件模式 singleton
    第二部分 职责型模式responsibility
    设计模式5 合成模式 COMPOSITE
    linux中xargs用法
    linux中du的用法
    linux中find的用法
    linux中grep注意
  • 原文地址:https://www.cnblogs.com/stoneniqiu/p/4324900.html
Copyright © 2020-2023  润新知