如何制作指向同一实体的列表和 属性

How to make a list and a property pointing to the same entity

我是 entity framework 的新手,即使我知道如何在 Merise 中做到这一点,我也无法先使用代码来做到这一点。

在实体用户中,我应该有一个外键'Promotion_Id'

在实体促销中,我应该有一个指向用户实体的外键 'Pilote_Id'。

事情是这样的:我还有一个促销列表,它是促销中所有用户的列表。 Pilote_Id是编队飞行员的Id,当然是用户

我尝试了以下方法:

    public class User : EntityWithId
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
        public string Phone { get; set; }
        public virtual Promotion Promotion { get; set; }     
    }
    public class Promotion : EntityWithNameAndId
    {
        //Site is another entity, the place where the promotion is 
        public virtual Site Site { get; set; }
        public List<User> Users { get; set; }
        public virtual User Pilote { get; set; }
    }

(注:EntityWithId只包含一个Id,EntityWithNameAndId继承自EntityWithId,只包含一个名字)

但它只会导致在名为 Promotion_Id 和 Promotion_Id1.

的用户中有 2 个外键

我已经通过更改

使整个事情正常进行

public virtual User Pilote { get; set; }

public virtual Guid PiloteId { get; set; }

但我希望我的实体具有一定的一致性,所以..有没有正确的方法来实现这一点?

您可能需要使用显式映射来实现此目的:

在您的上下文的 OnModelCreating() 中:

modelBuilder.Entity<User>()
   .HasOptional(u => u.Promotion)
   .WithRequired(p => p.Pilote)
   .Map(u => u.MapKey("PiloteId"); // EF6
   // .HasForeignKey("PilotId") // EF Core

这假设用户可能有也可能没有促销活动,但所有促销活动都有试播。 Promotion.Users 可能会按照惯例在促销 table 上使用 UserId 进行映射,但如果存在任何问题:

但是,这种方法有一个很大的警告,它与架构有关,而不是 EF。没有 restriction/guard 可以确保飞行员是与促销相关的用户之一。 PiloteId 可以指向任何用户,并且该用户的 promotionId 可能不同。

在任何情况下,管理谁是飞行员的逻辑都需要通过代码来完成,但这意味着要么检查 ID 的有效组合,要么像这样:

如果一个用户只能与 1 个促销相关联,并且该促销中的一个用户可以成为试点,那么您可以考虑向用户添加一个名为 "IsPilot" 的标志。

然后在促销中:

public virtual ICollection<User> Users { get; set; } = new List<User>();
[NotMapped]
public User Pilote
{
   get { return Users.SingleOrDefault(u => u.IsPilote); }
   set 
   {   
      var newPilote = Users.Single(u => u.UserId == value.UserId); // Ensure the user nominated for Pilote is associated with this Promotion.
      var existingPilote = Pilote;
      if (existingPilote != null)
          existingPilote.IsPilote = false;
      newPilote.IsPilote = true;
   }
}

如果可以将用户分配给多个促销活动,那么您需要更新架构和映射以支持用户和促销活动之间的多对多关系,例如包含 UserId 和 PromotionId 的 UserPromotions table .在这种情况下,我会考虑在这个 table / 链接实体中分配 IsPilote,但这同样需要逻辑来确保每次促销围绕 1 个飞行员进行规则,以及用户是否可以成为多个促销的飞行员。