简体   繁体   中英

EF - 2:Many relationship not working as expected

I have Payments between Users . A Payment has a FromUser and a ToUser . I'm testing out the entity relationships with the following:

            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

My question is - why does user2 not have any Payments ?

Class and fluent config:

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);
}

It can be due to many reasons, but, first things first, you mixed Data Annotations and Fluent API mappings. Why? I am not sure if it works as expected or not, but I am sure that it does not look right. Stick to one (I recommend Fluent API). Secondly, I suppose that, you should have two navigation properties at User for Payments . User.Payments does not mean much, do you want payments that the user paid, or the payments that were paid to user by one navigation property? . And you have to map only from one side. Finally, your models and mappings should be like below:

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);
    }
}

Note: virtual keyword is for Lazy loading and can be skipped if you do not need it.

Now it should work as expected. Just remember to test like:

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

Please note that, I suppose user1 and user2 both are tracked by EntityFramework, so EF can relate users with payments.

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