【问题标题】:How to create two-way Relation between two tables in Entity FrameWork如何在实体框架中的两个表之间创建双向关系
【发布时间】:2018-05-15 06:15:09
【问题描述】:

我有两个表,我想创建从 UserContact 的 1-n 关系并在 EF 中反转。这意味着我需要与 2 个目的地的 2 路关系,它们也是基表。 用户类中的Contact 表应该作为ICollection 引入,所以我的关系出错了,它们都是一边。check this picture 但是如果我删除ICollection,一切都是正确的。

我应该如何解决这个问题?

  public class User
  {
    [Key]
    public Guid Id {get; set;}       
    [ForeignKey("ContactId")]
    public virtual ICollection<Contact> Contacts {get; set;}        
    public Guid? ContactId {get;set;}
  }

  public class Contact
  {
    [Key]
    public Guid Id {get; set;}
    [ForeignKey("UserId")]
    public virtual User User {get; set;}
    public Guid? UserId {get; set;}
  }

如果我删除联系人check this picture 的外键:

我想要这些表之间的更多关系,但方向不同。 check this picture

【问题讨论】:

  • 删除public Guid? ContactId {get;set;}[ForeignKey("ContactId")]。您想要 UserContact 的 1-n 关系,因此应将 Contact 定义为集合;即public virtual ICollection&lt;Contact&gt; Contacts {get; set;}
  • 谢谢...我在您写的时候进行了测试...但我有一个从 "contact" 到 "user" 的 1-n 关系。我也需要与反向方向的更多关系。从“用户”到“联系人”
  • 为什么(你认为)你需要这种额外的关系?你会如何使用它?
  • 让我举个例子:我的用户表是给我老板的,联系表是给他的员工的,所以每个老板都可以有多名员工......所以在联系表中应该插入用户 ID,这意味着谁是你的老板?然后我想要老板 1 的一个联系人的名字也有另一个条件(对于与用户表有关系的其他表)所以我应该在我的用户表中有联系人 ID 和虚拟来从中获取数据。我希望我解释清楚。
  • 再次,您将如何使用它?使用更多的 C#(也许还有 SQL)来解决你的问题。

标签: c# entity-framework entity icollection


【解决方案1】:

有很多方法可以实现这一点。你可以这样做

  public class User
  {
    [Key]
    public Guid Id {get; set;}
    public virtual ICollection<Contact> Contacts { get; set; }
  }

  public class Contact
  {
    [Key]
    public Guid Id {get; set;}
    public virtual User User {get; set;}
  }

你也可以这样试试

  public class User
  {
    [Key]
    public Guid UserId {get; set;}
    public virtual ICollection<Contact> Contacts { get; set; }
  }

  public class Contact
  {
    [Key]
    public Guid Id {get; set;}
    public Guid UserId {get; set;}
    public virtual User User {get; set;}
  }

它包括外键属性UserId

欲了解更多信息,你可以去这个link

【讨论】:

  • 谢谢你的回答。我删除了你所说的外键,但我有一个从 "contact" 到 "user" 的 1-n 关系。我还需要一个与反向方向的关系。
  • 在此解决方案中,您有来自User ICollection&lt;Contact&gt; Contacts 导航属性以及来自ContactUser User 导航属性。不满足你的要求吗?
  • @MarzieKeshavarz 请查看修改后的答案。
  • 不,我需要 2 个关系,但是您建议的这段代码创建 1 个关系,我需要 1 个不同方向的关系
【解决方案2】:
  public class User
  {
    [Key]
    public Guid Id {get; set;}       
   // [ForeignKey("ContactId")]
    public virtual ICollection<Contact> Contacts {get; set;}        
   // public Guid? ContactId {get;set;}
  }

1-n 关系的 1 边没有外键。

【讨论】:

  • 谢谢...我在您写的时候进行了测试...但我有一个从 "contact" 到 "user" 的 1-n 关系。我也需要与反向方向的更多关系。从“用户”到“联系人”
  • 你已经有通讯录了,就是这个。当您还需要一个特殊的联系人时,即 HomeAddress 然后适当地命名它。目前还不清楚问题出在哪里。
  • 有时我需要创建 2 向关系... collection" 是对的。
  • 你还是不清楚。在 C# 中,关系是导航(虚拟)属性,这显然是一条 2 路。 SQL 中生成的内容取决于“约定”,该模型中应该有 2 个主键和 1 个外键。
  • 你是对的,他们可以交流,但在我的数据库中,如果我不创建 2 方关系,我无法丰富一些数据......这是因为我的一些外键可以为空还有一些不能为空...我只需要其中一个是 collection 的 2 方关系 .. 如果我创建这种关系,一切都很好。我可以与 collection 建立 2-side 1-n 关系吗?
【解决方案3】:

如果您需要从 User 到 Contact 的 1-n 关系,则需要额外的导航属性。要确定 EF 行为,您还可以配置模型。 这是一个例子。

[Table("User78")]
public class User
{
    [Key]
    public int Id { get; set; }
    public virtual ICollection<Contact> Contacts { get; set; }
    public virtual User MyPreferredUser { get; set; }
}

[Table("Contact78")]
public class Contact
{
    [Key]
    public int Id { get; set; }
    public virtual User User { get; set; }
}

public class Context : DbContext
{
    public Context()
    { }

这是上下文配置

    public Context(DbConnection connection)
        : base(connection, true)
    { }

    public DbSet<User> Users { get; set; }
    public DbSet<Contact> Contacts { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .HasMany(_ => _.Contacts)
            .WithOptional(_ => _.User)
            .Map(_ => _.MapKey("UserId"));

        modelBuilder.Entity<User>()
            .HasOptional(_ => _.MyPreferredUser)
            .WithMany()
            .Map(_ => _.MapKey("ContactId"));
    }
}

在此示例中,您无法使用 MyPreferredUser 关系从联系人导航到用户。如果需要,您需要添加从联系人到用户的新导航(ICollection 类型)。

这是迁移过程中EF生成的DML

ExecuteNonQuery==========
CREATE TABLE [Contact78] (
 [Id] int not null identity(1,1)
, [UserId] int null
);
ALTER TABLE [Contact78] ADD CONSTRAINT [PK_Contact78_a31c6496] PRIMARY KEY ([Id])
ExecuteNonQuery==========
CREATE TABLE [User78] (
 [Id] int not null identity(1,1)
, [ContactId] int null
);
ALTER TABLE [User78] ADD CONSTRAINT [PK_User78_a31c6496] PRIMARY KEY ([Id])
ExecuteNonQuery==========
CREATE INDEX [IX_UserId] ON [Contact78] ([UserId])
ExecuteNonQuery==========
CREATE INDEX [IX_ContactId] ON [User78] ([ContactId])
ExecuteNonQuery==========
ALTER TABLE [Contact78] ADD CONSTRAINT [FK_Contact78_User78_UserId] FOREIGN KEY ([UserId]) REFERENCES [User78] ([Id])
ExecuteNonQuery==========
ALTER TABLE [User78] ADD CONSTRAINT [FK_User78_User78_ContactId] FOREIGN KEY ([ContactId]) REFERENCES [User78] ([Id])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多