Search code examples
.net-coreentity-framework-coreeager-loading.net-core-3.0webapi

Eager loading only appear in some result


I am currently using .Net Core 3.0 and I'm building a Web API. I am trying to eager load some related data to the frontend.

I have the following classes and dbcontext setup.

    public class EntityCommon
    {
        public int Id { get; set; }
        public DateTime CreatedDatetime { get; set; }
    }

    public class UserAmountClaim: EntityCommon
    {
        public int UserId { get; set; }
        public AmountClaimType Type { get; set; }
        public int Amount{ get; set; }
        public int? RefereeId { get; set; }
        public AmountClaimStatus Status { get; set; }
        public DateTime? ClaimedDatetime { get; set; }

        [NotMapped]
        public virtual User Referee { get; set; }
    }

    public class User : EntityCommon
    {

        public string Name { get; set; }
        public string Password { get; set; }
        public UserStatus Status { get; set; }


        [NotMapped]
        public virtual UserAmountClaim UserAmountClaim { get; set; }
    }

DbContext

modelbuilder.Entity<UserAmountClaim>().ToTable("UserAmountClaim ", "dbo");
modelbuilder.Entity<UserAmountClaim>().Property(ucc => ucc.UserId).HasColumnName("fkUserId");
modelbuilder.Entity<UserAmountClaim>().Property(ucc => ucc.RefereeId).HasColumnName("fkRefereeId");
modelbuilder.Entity<UserAmountClaim>().Property(ucc => ucc.Type).HasConversion(new EnumToStringConverter<UserAmountClaim>());
modelbuilder.Entity<UserAmountClaim>().Property(ucc => ucc.CreatedDatetime).ValueGeneratedOnAdd();
modelbuilder.Entity<UserAmountClaim>().HasOne(ucc => ucc.Referee).WithOne(user => user.UserAmountClaim);

Startup.cs

services.AddControllers().AddNewtonsoftJson(options =>
{
    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    options.SerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-ddTHH:mm:ss" });
    options.SerializerSettings.Converters.Add(new StringEnumConverter());
    options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});

And also data such as below

Id  fkUserId    Type                Amount fkRefereeId  Status  ClaimedDateTime  CreatedDatetime
52  1           ReferralCommission  100    2            6       NULL             2020-04-18 15:19:34.203
53  1           ReferralCommission  100    2            6       NULL             2020-04-18 15:19:40.343
54  1           ReferralCommission  100    1            6       NULL             2020-04-18 15:36:44.017
55  1           ReferralCommission  100    1            6       NULL             2020-04-18 15:51:31.757

But when i execute the following code

var result = _dbContext.UserAmountClaim.Where(x => x.UserId == userId &&
                            x.Status == AmountClaimStatus.PendingUser &&
                            x.Type == AmountClaimType.ReferralCommission)
                            .Include(x => x.Referee)
                            .ToListAsync();

The referee is missing in the first and third item


{
    "userId": 1,
    "type": "ReferralCommission",
    "amount": 100,
    "status": "PendingUser",
    "id": 52,
    "createdDatetime": "2020-04-18T15:19:34"
},
{
    "userId": 1,
    "type": "ReferralCommission",
    "amount": 100,
    "refereeId": 2,
    "status": "PendingUser",
    "referee": {
        "id": 2,
        "name": "82109380918",
        "password": "",
        "status": "Valid",
        "createdDatetime": "2020-04-16T17:45:31",
    },
    "id": 53,
    "createdDatetime": "2020-04-18T15:19:40"
},
{
    "userId": 1,
    "type": "ReferralCommission",
    "credit": 100,
    "status": "PendingUser",
    "id": 54,
    "createdDatetime": "2020-04-18T15:36:44"
},
{
    "userId": 1,
    "type": "ReferralCommission",
    "amount": 100,
    "refereeId": 1,
    "status": "PendingUser",
    "referee": {
        "id": 1,
        "name": "31829389031",
        "password": "",
        "status": "Valid",
        "createdDatetime": "2020-04-16T17:45:31",
    },
    "id": 54,
    "createdDatetime": "2020-04-18T15:36:44"
}

This is happening all over other places that has the similar structure.

Anyone can enlighten me what's causing this and how to solve this ?


Solution

  • As pointed out by @IvanStoev, it was a mistaken in setting up the relationship and property class

    Modifying following works for me.

    public class User : EntityCommon
    {
         public string Name { get; set; }
         public string Password { get; set; }
         public UserStatus Status { get; set; }
         [NotMapped]
         public virtual List<UserAmountClaim> UserAmountClaim { get; set; }
    }
    

    DbContext

    modelbuilder.Entity<UserAmountClaim>().ToTable("UserAmountClaim ", "dbo");
    modelbuilder.Entity<UserAmountClaim>().Property(ucc => ucc.UserId).HasColumnName("fkUserId");
    modelbuilder.Entity<UserAmountClaim>().Property(ucc => ucc.RefereeId).HasColumnName("fkRefereeId");
    modelbuilder.Entity<UserAmountClaim>().Property(ucc => ucc.Type).HasConversion(new EnumToStringConverter<UserAmountClaim>());
    modelbuilder.Entity<UserAmountClaim>().Property(ucc => ucc.CreatedDatetime).ValueGeneratedOnAdd();
    modelbuilder.Entity<UserAmountClaim>().HasOne(ucc => ucc.Referee).WithMany(user => user.UserAmountClaim);
    

    Big thanks to @IvanStoev