locked
Error when retrieving associated users using a join table and Microsoft Identity RRS feed

  • Question

  • User986042657 posted

    I've facing an error that I am unsure of how to solve. I am trying to retrieve a list of users associated to an organization via a one to many join table. The error being thrown is:

    Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?)

    I cant seem to find a work around to this (and I'm teaching myself to code so my knowledge is limited).

    Is anyone able to provide some direction on how to resolve this? The error itself is in the OrganizationsRepository on the 3rd last line:

    return orgUsers;

    IOrganizationsRepository:

    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Outmatch.API.Models;
    
    namespace Outmatch.API.Data
    {
        public interface IOrganizationRepository
        {
            void Add<T>(T entity) where T: class;
            void Delete<T>(T entity) where T: class;
            Task<bool> SaveAll();
            Task<IEnumerable<Organizations>> GetOrganizations();
            Task<Organizations> GetOrganization(int id);
            Task<OrgToLoc> GetOwnees(int OrganizationId, int LocationId);
    
            // Begin Help on many to many 
            // Get users attached to an organization
            Task<IEnumerable<User>> GetOrgUsers(int organizationId);
            // Get locations attached to an organization
            Task<IEnumerable<Organizations>> GetOrganizationNameById(int LocationId);
            // End many to many help
        }
    }
    

    OrganizationsRepository:

    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.EntityFrameworkCore;
    using Outmatch.API.Helpers;
    using Outmatch.API.Models;
    
    namespace Outmatch.API.Data
    {
        public class OrganizationsRepository : IOrganizationRepository
        {
            private readonly DataContext _context;
            public OrganizationsRepository(DataContext context)
            {
                _context = context;
    
            }
            public void Add<T>(T entity) where T : class
            {
                _context.Add(entity);
            }
    
            public void Delete<T>(T entity) where T : class
            {
                _context.Remove(entity);
            }
    
            // get an organization only one of them).  Pass in the organization ID from the user interface, and pull the organization that corresponds to the 
            // id, returning it to the GUI 
            public async Task<Organizations> GetOrganization(int id)
            {
                var organization = await _context.Organization.FirstOrDefaultAsync(u => u.Id == id);
                return organization;
    
            }
    
            // Get the list of all organizations and return them to the GUI
            public async Task<IEnumerable<Organizations>> GetOrganizations()
            {
                var organizations = await _context.Organization.ToListAsync();
                return organizations;
            }
    
            public async Task<OrgToLoc> GetOwnees(int OrganizationId, int LocationId)
            {
                return await _context.LocationOwners.FirstOrDefaultAsync(u => u.OwnerId == OrganizationId && u.OwneeId == LocationId);
            }
    
            // Begin help many to many 
            public async Task<IEnumerable<Organizations>> GetOrganizationNameById(int LocationId)
            {
                var OrganizationName = await _context.Locations
                    .Include(l => l.Owners)
                    .Where(o => o.Id == LocationId)
                    .SelectMany(l => l.Owners.Select(on => on.Owner))
                    .ToListAsync();
    
                return OrganizationName;
            }
            // End help many to many 
    
            public async Task<bool> SaveAll()
            {
                return await _context.SaveChangesAsync() > 0;
            }
    
            public async Task<IEnumerable<User>> GetOrgUsers(int orgId)
        {
            var orgUsers = await _context.Organization
                .Include(u => u.UserId)
                .Where(u => u.Id == orgId)
                .SelectMany(u => u.UserId.Select(ui => ui.OrganizationId))
                .ToListAsync();
    
            return orgUsers;
        }
        }
    }
    

    UsersModel: 

    using System;
    using System.Collections.Generic;
    using Microsoft.AspNetCore.Identity;
    
    namespace Outmatch.API.Models
    {
        // List of properties for the User (Client) table in the db
        public class User : IdentityUser<int>
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public DateTime ActiveDate { get; set; }
            public DateTime EndDate { get; set; }
    
            // User Roles Management
            public virtual ICollection<UserRole> UserRoles { get; set; }
    
            // Organization to Client table ties
            public ICollection<OrgToClients> OrganizationId { get; set; }
        }
    }

    OrgToClients Model: 

    namespace Outmatch.API.Models
    {
        public class OrgToClients
        {
            public int OrganizationId { get; set; }
            public int UserId { get; set; }
            public User User { get; set; }
            public Organizations Organization { get; set; }
        }
    }
    

    Any assistance would be greatly appreciated.

    Friday, April 17, 2020 12:30 AM

Answers

  • User-854763662 posted

    Hi sapper6fd ,

    There is many-to-many relationships between User and Organization. Here is a working demo about getting user data as per the id of organization, you could refer to and make the modification.

    User-Organization ,you could refer to many-to-many relationship in EF Core 

    public class ApplicationUser:IdentityUser
    {
            public int CompanyId { get; set; }
            // Organization to Client table ties
            public ICollection<OrgToClients> OrgToClients { get; set; }
    }
    
    public class Organizations
    {
            public  int Id { get; set; }
            public string OrganizationName { get; set; }
                
            // Organization to Client table ties
            public ICollection<OrgToClients> OrgToClients { get; set; }
    }
    
    
    public class OrgToClients
    {
            public int OrganizationId { get; set; }
            public string UserId { get; set; }
            public ApplicationUser User { get; set; }
            public Organizations Organization { get; set; }
    }
    
    //DbContext
    public class ApplicationDbContext : IdentityDbContext
    {
            public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
                : base(options)
            {
            }
    
            public DbSet<ApplicationUser> ApplicationUser { get;set;}
            public DbSet<Organizations> Organization { get;set; }
            public DbSet<OrgToClients> OrgToClients { get;set; }
    
            protected override void OnModelCreating(ModelBuilder builder)
            {
                base.OnModelCreating(builder);
    
                #region User-Organization Many-to-Many
    
                builder.Entity<OrgToClients>()
                    .HasKey(otc => new { otc.UserId, otc.OrganizationId });
    
                builder.Entity<OrgToClients>()
                    .HasOne(otc => otc.Organization)
                    .WithMany(o => o.OrgToClients)
                    .HasForeignKey(otc => otc.OrganizationId);
    
                builder.Entity<OrgToClients>()
                    .HasOne(otc => otc.User)
                    .WithMany(o => o.OrgToClients)
                    .HasForeignKey(otc => otc.UserId);
                #endregion
               
            }
    }

    OrganizationsRepository

    public async Task<IEnumerable<ApplicationUser>> GetOrgUsers(int orgId)
    {
                var orgUsers = await _context.ApplicationUser
                    .Include(a => a.OrgToClients)
                    .Where(a => a.OrgToClients.Any(o => o.OrganizationId == orgId))
                    .ToListAsync();
                return orgUsers;
    }

    Test Controller

    public Task<IEnumerable<ApplicationUser>> GetUser(int orgId)
    {
          var data=_organizationRepository.GetOrgUsers(orgId);
          return data;
    }

    Result

    Best Regards,

    Sherry

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, April 17, 2020 3:22 AM

All replies

  • User-854763662 posted

    Hi sapper6fd ,

    There is many-to-many relationships between User and Organization. Here is a working demo about getting user data as per the id of organization, you could refer to and make the modification.

    User-Organization ,you could refer to many-to-many relationship in EF Core 

    public class ApplicationUser:IdentityUser
    {
            public int CompanyId { get; set; }
            // Organization to Client table ties
            public ICollection<OrgToClients> OrgToClients { get; set; }
    }
    
    public class Organizations
    {
            public  int Id { get; set; }
            public string OrganizationName { get; set; }
                
            // Organization to Client table ties
            public ICollection<OrgToClients> OrgToClients { get; set; }
    }
    
    
    public class OrgToClients
    {
            public int OrganizationId { get; set; }
            public string UserId { get; set; }
            public ApplicationUser User { get; set; }
            public Organizations Organization { get; set; }
    }
    
    //DbContext
    public class ApplicationDbContext : IdentityDbContext
    {
            public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
                : base(options)
            {
            }
    
            public DbSet<ApplicationUser> ApplicationUser { get;set;}
            public DbSet<Organizations> Organization { get;set; }
            public DbSet<OrgToClients> OrgToClients { get;set; }
    
            protected override void OnModelCreating(ModelBuilder builder)
            {
                base.OnModelCreating(builder);
    
                #region User-Organization Many-to-Many
    
                builder.Entity<OrgToClients>()
                    .HasKey(otc => new { otc.UserId, otc.OrganizationId });
    
                builder.Entity<OrgToClients>()
                    .HasOne(otc => otc.Organization)
                    .WithMany(o => o.OrgToClients)
                    .HasForeignKey(otc => otc.OrganizationId);
    
                builder.Entity<OrgToClients>()
                    .HasOne(otc => otc.User)
                    .WithMany(o => o.OrgToClients)
                    .HasForeignKey(otc => otc.UserId);
                #endregion
               
            }
    }

    OrganizationsRepository

    public async Task<IEnumerable<ApplicationUser>> GetOrgUsers(int orgId)
    {
                var orgUsers = await _context.ApplicationUser
                    .Include(a => a.OrgToClients)
                    .Where(a => a.OrgToClients.Any(o => o.OrganizationId == orgId))
                    .ToListAsync();
                return orgUsers;
    }

    Test Controller

    public Task<IEnumerable<ApplicationUser>> GetUser(int orgId)
    {
          var data=_organizationRepository.GetOrgUsers(orgId);
          return data;
    }

    Result

    Best Regards,

    Sherry

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, April 17, 2020 3:22 AM
  • User986042657 posted

    With some adjustments, I was able to get this corrected. The GetOrgUsers method in the OrganizationsRepository need to be adjusted to reflect:

        public async Task<IEnumerable<User>> GetOrgUsers(int orgId)
    {
        var orgUsers = await _context.Organization
            .Include(u => u.UserId)
            .Where(u => u.Id == orgId)
            .SelectMany(u => u.UserId.Select(ui => ui.OrganizationId))
            .ToListAsync();
    
        return orgUsers;
    }

    and I needed too add the following to the Organizations Model:

    public ICollection<OrgToClients> OrganizationId { get; set; }

    Problem solved.

    Friday, April 17, 2020 4:56 AM
  • User986042657 posted

    Thanks Sheery. Looks like you beat me to it.  I did figure it out (using a different method) but I am looking at your solution as well to see how it works. 

    Thanks again!

    Friday, April 17, 2020 4:57 AM