技术, EF

Entity Framework Code First 两个字段关联到同一张表

之前也遇到过类似的问题,属于Code First中稍微复杂点的关系处理,现将解决方法记录下来。

场景:

某网上书城欲推出书券功能,书券购买之后,会有一个唯一的Id,可用来直接兑换某本书。书券可以自己兑换,也可以将ID送给朋友来兑换。现在我们需要将书券的购买者和兑换者都记录下来。

类的设计和注意事项:

public class BookCoupon
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    [Index("BookCouponIdIndex")]
    public Guid BookCouponId { get; set; }

    [Index("BookIdIndex")]
    public int BookId { get; set; }

    [ForeignKey("BookId")]
    public virtual Book Book { get; set; }

    [Index("BuyUserIdIndex")]
    public string BuyUserId { get; set; }

    [ForeignKey("BuyUserId")]
    public virtual User BuyUser { get; set; }

    [Index("RedeemUserIdIndex")]
    public string RedeemUserId { get; set; }

    [ForeignKey("RedeemUserId")]
    public virtual User RedeemUser { get; set; }

    public DateTime BuyTime { get; set; }

    public DateTime RedeemTime { get; set; }
}
public class User
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    [Index("UserIdIndex")]
    public Guid UserId { get; set; }

    public string UserName { get; set; }

    public virtual ICollection<BookCoupon> BuyCoupons { get; set; }

    public virtual ICollection<BookCoupon> RedeemCoupons { get; set; }

    ......
}

另外,在DbContext中需要override OnModelCreating方法:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<ApplicationUser>().HasMany(u => u.BuyCoupons).WithRequired(n => n.BuyUser).WillCascadeOnDelete(false);
    modelBuilder.Entity<ApplicationUser>().HasMany(u => u.RedeemCoupons).WithRequired(n => n.RedeemUser).WillCascadeOnDelete(false);
}

注意最后的.WillCascadeOnDelete(false),因为在这样多对多的绑定中,使用级联删除会报错。

by HADB @ Newegg

您已成功订阅 HADB.ME
真棒!下一步,完成结账以便解锁 HADB.ME
欢迎回来!您已登录成功。
登录失败,请重试。
操作成功!您的账户已全面激活,现在您有所有内容的权限了。
错误!Stripe 结账失败。
成功!您的账单信息已更新。
错误!账单信息更新失败。