EF - 2:许多关系没有按预期工作

时间:2016-08-18 02:51:45

标签: c# entity-framework ef-code-first

Payments之间UsersPayment有一个FromUser和一个ToUser。我用以下方法测试了实体关系:

            var newPayment = new Payment() {
                FromUserId = user1.UserId,
                ToUserId = user2.UserId
            };
            db.Payments.Add(newPayment);
            db.SaveChanges();
            var tempPaymentId = user1.Payments.First().PaymentId;
            newPayment = db.Payments.First(s => s.PaymentId == tempPaymentId);
            Assert.AreEqual(newPayment.FromUserId, user1.UserId); // true
            Assert.AreEqual(newPayment.ToUserId, user2.UserId); // true
            Assert.AreEqual(user1.Payments.Count(), 1); // true
            Assert.AreEqual(user2.Payments.Count(), 1); // false

我的问题是 - 为什么user2没有Payments

分类和流畅的配置:

public class Payment {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int PaymentId { get; set; }

        [ForeignKey("FromUser")]
        public int FromUserId { get; set; }
        public User FromUser { get; set; }

        [ForeignKey("ToUser")]
        public int ToUserId { get; set; }
        public User ToUser { get; set; }
}

public PaymentConfiguration() {
        HasRequired(s => s.FromUser);
        HasRequired(s => s.ToUser);
}

public UserConfiguration() {
        // One-to-Many
        HasMany(s => s.Payments);
}

1 个答案:

答案 0 :(得分:0)

这可能是由于许多原因,但首先,您混合了数据注释 Fluent API 映射。为什么?我不确定它是否按预期工作,但我确信它看起来不正确。坚持一个(我推荐Fluent API)。其次,我想,User Payments的{​​{1}}应该有两个导航属性。 User.Payments并不意味着什么,您是希望用户付款还是通过一个导航属性向用户付款?。而且你必须只从一侧进行映射。最后,您的模型和映射应如下所示:

public class User
{
    public int UserId { get; set; }

    // Navigation properties
    public virtual ICollection<Payment> PaymentsFromUser { get; set; }
    public virtual ICollection<Payment> PaymentsToUser { get; set; }    
}

public class UserConfiguration
    : IEntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        // Primary key
        HasKey(m => m.UserId);

        Property(m => m.PaymentId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}

public class Payment 
{
    public int PaymentId { get; set; }
    public int FromUserId { get; set; }
    public int ToUserId { get; set; }

    // Navigation properties
    public virtual User FromUser { get; set; }
    public virtual User ToUser { get; set; }
}

public class PaymentConfiguration 
    : IEntityTypeConfiguration<Payment>
{
    public PaymentConfiguration()
    {
        // Primary key
        HasKey(m => m.PaymentId);

        Property(m => m.PaymentId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        // Relationship mappings
        HasRequired(m => m.FromUser)
            .WithMany(m => m.PaymentsFromUser)
            .HasForeignKey(m => m.FromUserId)
            .WillCascadeOnDelete(true);

        HasRequired(m => m.ToUser)
            .WithMany(m => m.PaymentsToUser)
            .HasForeignKey(m => m.ToUserId)
            .WillCascadeOnDelete(true);
    }
}

注意: virtual关键字适用于Lazy loading,如果您不需要,可以跳过。

现在它应该按预期工作。请记住测试如下:

Assert.AreEqual(user1.PaymentsFromUser.Count(), 1);
Assert.AreEqual(user2.PaymentsToUser.Count(), 1);

请注意,我认为user1user2都由EntityFramework跟踪,因此EF可以将用户与付款相关联。