Search code examples
c#asp.netentity-framework-coreaspnetboilerplate

Entities aren't passed in many-to-many relationship


I have created a many-to-many relation EventUser which holds the userId, EventId and the User and Event objects, aswell as an isPresent boolean which I use to manage the presence for the User for that Event.

I create the EventUser by setting both the Id's and objects, and then adding it to the Event's EventUser List. When I get the Events from the database however, the list of EventUsers only returns data the UserId, EventId and the IsPresent fields, the User and Event fields return null.

These are my classes:

User entity

public class User : AbpUser<User>
    {
        public const string DefaultPassword = "123qwe";
        public string Instrument { get; set; }
        public virtual ICollection<EventUser> EventUsers { get; set; }

        public static string CreateRandomPassword()
        {
            return Guid.NewGuid().ToString("N").Truncate(16);
        }

        public static User CreateTenantAdminUser(int tenantId, string emailAddress)
        {
            var user = new User
            {
                TenantId = tenantId,
                UserName = AdminUserName,
                Name = AdminUserName,
                Surname = AdminUserName,
                EmailAddress = emailAddress,
                Roles = new List<UserRole>(),
            };

            user.SetNormalizedNames();

            return user;
        }
    }

Event entity

    public class Event : Entity
    {
        [Required]
        public string Name { get; set; }

        [Required]
        public string Location { get; set; }
        public string Address { get; set; }

        public DateTime StartTime { get; set; }
        public DateTime EndTime { get; set; }

        public bool IsConfirmed { get; set; }

        public int GroupId { get; set; }

        public virtual ICollection<EventUser> EventUsers { get; set; }

        public Event()
        {
            EventUsers = new List<EventUser>();
        }
    }

EventUser class

    public class EventUser : Entity
    {
        public int EventId { get; set; }
        public Event Event { get; set; }
        public long UserId { get; set; }
        public User User { get; set; }

        public bool IsPresent { get; set; }
    }

OnModelCreating method in my DbContext in which i create the many-to-many relationship

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<EventUser>().HasKey(eu => new { eu.EventId, eu.UserId }); //.isUnique()?
            modelBuilder.Entity<EventUser>().HasOne(eu => eu.Event)
                .WithMany(e => e.EventUsers)
                .HasForeignKey(eu => eu.EventId);
            modelBuilder.Entity<EventUser>().HasOne(eu => eu.User)
                .WithMany(u => u.EventUsers)
                .HasForeignKey(eu => eu.UserId);
        }

AddGroupUsersToEvent method in the EventAppService in which I create and add all the users of a group to the event as EventUsers.

        public void AddAllEventUsersFromGroup(AddAllEventUsersFromGroupDto dto)
        {
            var e = _eventManager.GetEventById(dto.EventId);
            var g = _groupManager.QueryGroups().FirstOrDefault(x => x.Id == dto.GroupId);

            foreach (var user in g.Users)
            {
                var eu = new EventUser
                {
                    EventId = e.Id,
                    Event = e,
                    UserId = user.Id,
                    User = user
                };
                e.EventUsers.Add(eu);
            }
            _eventManager.Update(e);
        }

ListAll method in the EventAppService in which I list all the events

        public IEnumerable<EventDto> ListAll()
        {
            var result = _eventManager.QueryEvents().Select(e => new EventDto
            {
                Id = e.Id,
                Name = e.Name,
                Location = e.Location,
                Address = e.Address,
                StartTime = e.StartTime,
                EndTime = e.EndTime,
                GroupId = e.GroupId,
                EventUsers = e.EventUsers
            }).OrderBy(e => e.StartTime).ToList();
            return result;
        }

If I run the ListAll method in Swagger it returns the EventUsers list from an event like this:

      "eventUsers": [
        {
          "eventId": 3,
          "event": null,
          "userId": 4,
          "user": null,
          "isPresent": true,
          "id": 0
        }
    ]

Do I have to include the event and user object somewhere when getting the Events? While debugging I found out that the Event and User objects are fine when I use them to create the EventUser, but are returned as null once I get the event.


Solution

  • Aaron's answer worked for me! The only thing i had to do, was to call the ToList() method after the statement because it expects an ICollection and not an IEnumerable.