简体   繁体   English

在HasOptional()中映射外键。实体框架6中的WithOptionalDependent()关系

[英]Mapping foreign key in HasOptional().WithOptionalDependent() relation in Entity Framework 6

I have the following data-model in Entity Framework 6.1.3: 我在Entity Framework 6.1.3中有以下数据模型:

using System.Data.Entity;

public class Student
{
    public int Id { get; set; }
    public virtual Contact Contact { get; set; }
}

public class Contact
{
    public int Id { get; set; }
    public virtual Student Student { get; set; }
}

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder builder)
    {
        builder.Entity<Contact>()
            .HasOptional(x => x.Student)
            .WithOptionalDependent(x => x.Contact)
            .WillCascadeOnDelete(true);
    }
}

public static class Program
{
    private static void Main()
    {
        Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());

        using (var context = new MyContext())
            context.Database.Initialize(force: true);
    }
}

When I launch this code, I get exactly the right table structure I am aiming for: 当我启动这段代码时,我得到了正确的表格结构:

dbo.Contacts
    Id (PK)
    Student_Id (FK, NULL, CASCADE ON DELETE)

dbo.Students
    Id (PK)

However, now I would like to add the Student_Id property to be available in the Contact entity. 但是,现在我想添加Student_Id属性以在Contact实体中可用。 So I can read the Student_Id without needing to join the other table through .Student.Id navigation. 所以我可以阅读Student_Id而无需通过.Student.Id导航加入其他表。

If I add the property to the Contact entity, I end up either with two columns Student_Id and Student_Id1 , or I end up with an error message saying Each property name in a type must be unique. 如果我将该属性添加到Contact实体,我最终Student_Id两列Student_IdStudent_Id1 ,或者我最后会收到一条错误消息,指出Each property name in a type must be unique. .

The column is already in the database, all I need is to have it in the entity as well, why is it so much trouble? 该列已经在数据库中,我需要的只是将它放在实体中,为什么这么麻烦? Is there a solution? 有解决方案吗?

I managed to get a response from the Entity Framework Program Manager after asking on GitHub . 向GitHub询问后,我设法得到了实体框架项目经理的回复。

Unfortunately this is a limitation of EF6. 不幸的是,这是EF6的限制。 You can not have a foreign key property in a one-to-one relationship, unless it is also the primary key property. 您不能以一对一的关系拥有外键属性,除非它也是主键属性。 This is essentially because EF6 doesn't support alternate keys/unique indexes, so you can't enforce that a non-primary key property is unique. 这主要是因为EF6不支持备用键/唯一索引,因此您无法强制非主键属性是唯一的。 The fact that you can do it when the foreign key property isn't in the entity is a bit of a quirk... but obviously not something we would remove 😄. 当外键属性不在实体中时你可以这样做的事实有点怪癖......但显然不是我们要删除的东西😄。

BTW alternate keys (and therefore this scenario) is supported in EF Core. EF Core支持BTW备用密钥(因此也支持此方案)。

– Rowan Miller @ https://github.com/aspnet/EntityFramework6/issues/159#issuecomment-274889438 - Rowan Miller @ https://github.com/aspnet/EntityFramework6/issues/159#issuecomment-274889438

If you want to declare the FK property in the dependent entity in an one to one relationship, I'm afraid you must use it as a PK too. 如果你想以一对一的关系在依赖实体中声明FK属性,我恐怕你也必须将它用作PK。 EF Code First requires that PK of the dependent entity must be FK of the relationship too: EF Code First 要求依赖实体的PK也必须是关系的FK:

public class Contact
{
    [Key,ForeignKey("Student")]
    public int StudentId { get; set; }
    public virtual Student Student { get; set; }
}

But I think this is not what you are looking for. 但我认为这不是你想要的。 So, I think you have three options here: 所以,我认为你有三个选择:

  • You preserve your current relationship configuration. 您保留当前的关系配置。
  • Create an authentic one to one relationship . 创建真实的一对一关系
  • Create an one to many relationship 创建一对多的关系

By my experience the last one is the most adjusted to what are you trying to achieve (but that is my opinion). 根据我的经验,最后一个是你想要实现的最多调整(但这是我的意见)。 In this case you can work with the Fk property as you want, the only is you need to change the Contact navigation property on Student by a collection (or omit this nav. property and create an unidirectional relationship): 在这种情况下,您可以根据需要使用Fk属性,唯一需要通过集合更改Student上的Contact导航属性(或省略此nav。属性并创建单向关系):

public class Student
{
    public int Id { get; set; }
    public virtual ICollection<Contact> Contacts { get; set; }
}

The configuration would be this way: 配置将是这样的:

 builder.Entity<Contact>()
        .HasOptional(x => x.Student)
        .WithMany(x => x.Contacts)
        .HasForeignKey(x => x.StudentId)
        .WillCascadeOnDelete(true);

Update 更新

A fourth option could be create two unidirectional relationships: 第四个选项可以创建两个单向关系:

 builder.Entity<Contact>()
        .HasOptional(x => x.Student)
        .WithMany()
        .HasForeignKey(x => x.StudentId)
        .WillCascadeOnDelete(true);

 builder.Entity<Student>()
        .HasOptional(x => x.Contact)
        .WithMany()
        .HasForeignKey(x => x.ContactId)
        .WillCascadeOnDelete(true);

But this option breaks the real relation between the two tables. 但是这个选项打破了两个表之间的真实关系。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM