简体   繁体   中英

How to create 2 string foreign keys pointing at the same unique string column?

I have an entity "Player" that has a "Guid" property of type string, with the unique constraint.

I have a "PlayerData" entity, that has the properties "PlayerGuid", "OpponentPlayerGuid" of type string.

How do I use EF Core to make sure PlayerGuid and OpponentPlayerGuid properties accept values only found inside Player.Guid property?

I've tried various things, from probably 5+ different answers on stackoverflow, none of which helped me work this out.

PlayerData entity

public class PlayerData
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public int AttackLevel { get; set; } = 0;
        public int DefenseLevel { get; set; } = 0;
        [InverseProperty("Guid")]
        public string PlayerGuid { get; set; }
        public Player Player { get; set; }
        //[ForeignKey("OpponentPlayerGuid")]
        //public string OpponentPlayerGuid { get; set; }
        public int WinStreak { get; set; } = 0;
        public double Armor { get; set; }
        public double Health { get; set; }
        public bool Acted { get; set; }
        public ActionType LastAction { get; set; }


    }

Player entity

    public class Player
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        [ForeignKey("SessionId")]
        public int? SessionId { get; set; }
        public Session Session { get; set; }
        [Required,MaxLength(36)]
        public string Guid { get; set; }
        public DateTime? BanTime { get; set; }

        public List<PlayerData> PlayerDatas { get; set; }


    }

You need to specify Alternate key on guid. And then configure foreign keys to it. Do it by using fluent API. Examples of usage here: https://docs.microsoft.com/en-US/ef/core/modeling/alternate-keys .

In your DbContext class:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<PlayerData>()
        .HasOne(e => e.Player)
        .WithMany() // If its a one to one relationsship, specify 'WithOne()' here
        .HasForeignKey(e => e.PlayerGuid)
        .OnDelete(DeleteBehavior.Restrict);

    modelBuilder.Entity<PlayerData>()
        .HasOne(e => e.OpponentPlayer)
        .WithMany()
        .HasForeignKey(e => e.OpponentPlayerGuid)
        .OnDelete(DeleteBehavior.Restrict);
}

On a side note: You should use the value type Guid , provided by the BCL, instead of strings. That way your ID's will always be a Guid.

If you don't mind me asking, is there any specific reason why you are not using Id to reference Player and OpponentPlayer? Then you can use foreign key to reference Player table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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