在实体框架代码中为同一表定义多个外键 [英] Defining multiple Foreign Key for the Same table in Entity Framework Code First

查看:151
本文介绍了在实体框架代码中为同一表定义多个外键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的MVC应用程序中有两个实体,我用Entity Framework 6 Code First方法填充数据库。学生实体有两个城市编号;其中一个为BirthCity,另一个为WorkingCity。当我如上定义外键时,迁移后在Student表中创建一个名为City_ID的额外列。认为有错误或如何定义这些FK?感谢提前。



学生:

  public class Student 
{
public int ID {get;组; }

public string Name {get;组; }

public string Surname {get;组; }

public int BirthCityID {get;组; }

public int LivingCityID {get;组; }


[ForeignKey(BirthCityID)]
public virtual City BirthCity {get;组; }

[ForeignKey(LivingCityID)]
public virtual City LivingCity {get;组; }
}




城市:

  public class City 
{
public int ID {get;组; }

public string CityName {get;组; }


public virtual ICollection< Student>学生{get;组; }
}


解决方案

您需要提供一些附加的配置.Code第一个约定可以识别双向关系,但不是当两个实体之间有
多个双向关系时。您可以添加配置(使用数据注释 Fluent API )将此
信息呈现给模型构建器。使用数据注释,您将使用一个注释
,名为 InverseProperty 。使用Fluent API,您将使用 Has / 方法的组合来指定这些关系。



使用数据注释可能是这样的:

  public class Student 
{
public int ID {get;组; }

public string Name {get;组; }

public string Surname {get;组; }

public int BirthCityID {get;组; }

public int LivingCityID {get;组; }


[ForeignKey(BirthCityID)]
[InverseProperty(Students)]
public virtual City BirthCity {get;组; }

[ForeignKey(LivingCityID)]
public virtual City LivingCity {get;组; }
}

这样你就可以明确指出你想将 BirthCity 导航属性与学生导航属性在关系的另一端。



使用 Fluent Api 可能是这样的:

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity< Student>()。HasRequired(m => m.BirthCity)
.WithMany(m => m.Students).HasForeignKey(m => .BirthCityId);
modelBuilder.Entity< Student>()。HasRequired(m => m.LivingCity)
.WithMany()。HasForeignKey(m => m.LivingCityId);
}

使用最后一个解决方案,您不需要使用任何attibute。 p>

现在,@ChristPratt的建议在 City 中收集了学生 code>每个关系的类都是非常有用的。如果这样做,那么使用数据注释的配置可能是这样的:

  public class Student 
{
public int ID {get;组; }

public string Name {get;组; }

public string Surname {get;组; }

public int BirthCityID {get;组; }

public int LivingCityID {get;组; }


[ForeignKey(BirthCityID)]
[InverseProperty(BirthCityStudents)]
public virtual City BirthCity {get;组; }

[ForeignKey(LivingCityID)]
[InverseProperty(LivingCityStudents)]
public virtual City LivingCity {get;组; }
}

或使用 Fluent Api

$ b

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity< Student>() .HasRequired(m => m.BirthCity)
.WithMany(m => m.BirthCityStudents).HasForeignKey(m => m.BirthCityId);
modelBuilder.Entity< Student>()。HasRequired(m => m.LivingCity)
.WithMany(m => m.LivingCityStudents).HasForeignKey(m => m.LivingCityId);
}


I have two entities in my MVC application and I populated the database with Entity Framework 6 Code First approach. There are two city id in the Student entity; one of them for BirthCity, the other for WorkingCity. When I define the foreign keys as above an extra column is created named City_ID in the Student table after migration. Id there a mistake or how to define these FKs? Thanks in advance.

Student:

public class Student
{
    public int ID { get; set; }

    public string Name { get; set; }

    public string Surname { get; set; }

    public int BirthCityID { get; set; }

    public int LivingCityID { get; set; }


    [ForeignKey("BirthCityID")]
    public virtual City BirthCity { get; set; }

    [ForeignKey("LivingCityID")]
    public virtual City LivingCity { get; set; }
}


City:

public class City
{
    public int ID { get; set; }

    public string CityName { get; set; }


    public virtual ICollection<Student> Students { get; set; }
}

解决方案

To achieve what you want you need to provide some aditional configuration.Code First convention can identify bidirectional relationships, but not when there are multiple bidirectional relationships between two entities.You can add configuration (using Data Annotations or the Fluent API) to present this information to the model builder. With Data Annotations, you’ll use an annotation called InverseProperty. With the Fluent API, you’ll use a combination of the Has/With methods to specify the correct ends of these relationships.

Using Data Annotations could be like this:

public class Student
{
  public int ID { get; set; }

  public string Name { get; set; }

  public string Surname { get; set; }

  public int BirthCityID { get; set; }

  public int LivingCityID { get; set; }


  [ForeignKey("BirthCityID")]
  [InverseProperty("Students")]
  public virtual City BirthCity { get; set; }

  [ForeignKey("LivingCityID")]
  public virtual City LivingCity { get; set; }
}

This way you specifying explicitly that you want to relate the BirthCity navigation property with Students navigation property in the other end of the relationship.

Using Fluent Api could be like this:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Student>().HasRequired(m => m.BirthCity)
                                 .WithMany(m => m.Students).HasForeignKey(m=>m.BirthCityId);
     modelBuilder.Entity<Student>().HasRequired(m => m.LivingCity)
                                 .WithMany().HasForeignKey(m=>m.LivingCityId);
}

With this last solution you don't need to use any attibute.

Now, the suggestion of @ChristPratt in have a collection of Student in your City class for each relationship is really useful. If you do that, then the configurations using Data Annotations could be this way:

public class Student
{
  public int ID { get; set; }

  public string Name { get; set; }

  public string Surname { get; set; }

  public int BirthCityID { get; set; }

  public int LivingCityID { get; set; }


  [ForeignKey("BirthCityID")]
  [InverseProperty("BirthCityStudents")]
  public virtual City BirthCity { get; set; }

  [ForeignKey("LivingCityID")]
  [InverseProperty("LivingCityStudents")]
  public virtual City LivingCity { get; set; }
}

Or using Fluent Api following the same idea:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Student>().HasRequired(m => m.BirthCity)
               .WithMany(m => m.BirthCityStudents).HasForeignKey(m=>m.BirthCityId);
     modelBuilder.Entity<Student>().HasRequired(m => m.LivingCity)
               .WithMany(m => m.LivingCityStudents).HasForeignKey(m=>m.LivingCityId);
}

这篇关于在实体框架代码中为同一表定义多个外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆