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

时间:2015-01-07 15:03:35

标签: c# entity-framework

我有两个班级

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。这对我来说真的没有意义。

3 个答案:

答案 0 :(得分:2)

这是因为这是您告诉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

答案 1 :(得分:0)

所以我不完全确定如何使用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; }
}

答案 2 :(得分:0)

问题只是说两个集合应该是ICollection&lt;&gt;而不是IList&lt;&gt;