Entity Framework 同一个表的两个复合外键,backref 关系不起作用

Entity Framework two composite foreign key to same table, backref relation not working

我有两个类

public class AuctionModel
{
    [Key]
    public int Id { get; set; }

    public virtual UserModel Seller { get; set; }
    public string SellerUsername { get; set; }
    public string SellerSiteName { get; set; }

    public string CurrentWinnerUsername { get; set; }
    public string CurrentWinnerSiteName { get; set; }
    public virtual UserModel CurrentWinner { get; set; }
}

    public class UserModel : Base
{
    [Key]
    [Column(Order = 2)]
    public string Username { get; set; }

    [Key]
    [Column(Order = 1)]
    public string SiteName { get; set; }

    public virtual SiteModel Site { get; set; }

    public List<AuctionModel> Auctions { get; set; }
    public List<AuctionModel> WinningAuctions { get; set; } 
}

而 Fluent Api 将关系指定为

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

        modelBuilder.Entity<AuctionModel>()
            .HasRequired(a => a.Seller)
            .WithMany(u => u.Auctions)
            .HasForeignKey(a => new {a.SellerUsername, a.SellerSiteName});

        modelBuilder.Entity<AuctionModel>()
            .HasOptional(a => a.CurrentWinner)
            .WithMany(u => u.WinningAuctions)
            .HasForeignKey(a => new {a.CurrentWinnerSiteName, a.CurrentWinnerUsername});
    }

据我所知,这应该可以正常工作,但实际情况是 UserModel.Auctions 和 CurrentModel.WinningAuctions 始终为空。我知道对象已附加,因为我检查过并且即使在我将对象保存到数据库后关系也为空。

更新:

return context.Users.Include("MyAuctions").Include("WinningAuctions").First(u => u.Username == userName && u.SiteName == siteName);

使用 Includes 加载数据,加载关系。这在某种程度上是可以预料的,但即使我将关系更改为

    public virtual List<AuctionModel> MyAuctions { get; set; }
    public virtual List<AuctionModel> WinningAuctions { get; set; }

我仍然必须使用 Include,否则我会得到 null。这对我来说真的没有意义。

所以我不完全确定如何使用 Fluent API 解决此问题,但以下是使用数据注释的方法:

public class AuctionModel
{
    [Key]
    public int Id { get; set; }

    [Required, ForeignKey("Seller"), Column(Order = 2)]
    public string SellerUsername { get; set; }

    [Required, ForeignKey("Seller"), Column(Order = 3)]
    public string SellerSiteName { get; set; }

    [ForeignKey("CurrentWinner"), Column(Order = 4)]
    public string CurrentWinnerUsername { get; set; }

    [ForeignKey("CurrentWinner"), Column(Order = 5)]
    public string CurrentWinnerSiteName { get; set; }

    public virtual UserModel Seller { get; set; }
    public virtual UserModel CurrentWinner { get; set; }
}

发生这种情况是因为这是您告诉 EF 加载数据的方式。要加载 Auctions 和 WinningAuctions 属性,您需要指定您想要包含然后使用 Include 方法(这称为 Eagerly Loading)显式地包含:

var usertest = db.Users.Include(u => u.WinningAuctions).Include(u => u.Auctions).FirstOrDefault(u => u.Username == "Albert" && u.SiteName == "localhost");

如果您将集合属性更改为 virtual,则无需执行包含。

public class UserModel
{
    public virtual List<AuctionModel> Auctions { get; set; }
    public virtual List<AuctionModel> WinningAuctions { get; set; }
}

任何虚拟集合都将延迟加载,除非您特别标记它们。

如果您想详细了解 EF 如何加载数据以及如何配置它,请查看此 link

更新

如果延迟加载行为仍然不起作用,您需要检查您的模型 类 是否满足需要 EF 创建代理的条件 类。看看这个link.

问题 war 只是两个集合应该是 ICollection<> 而不是 IList<>