Svit_O
Svit_O

Reputation: 1

Cannot cast 'Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1[Microsoft.AspNetCore.Identity.IdentityUser`1[System.Int32]]'

PROBLEM:

System.InvalidCastException: 'Unable to cast object of type 'Microsoft.EntityFrameworkCore.Internal.InternalDbSet1[Microsoft.AspNetCore.Identity.IdentityUser1[System.Int32]]' to type 'System.Linq.IQueryable`1[DAL.User]'.'

RELEVANT CODE:

...
public class SocialNetworkDbContext : IdentityDbContext<IdentityUser<int>, IdentityRole<int>, int> 
...
public IQueryable<User> FindAll()
        {
            var allUsers = (IQueryable<User>)_socialNetworkDbContext.Users;
            if (allUsers == null)
            {
                throw new NoRecordFoundException();
            }
            return allUsers;

TRIED:

  1. public class SocialNetworkDbContext : IdentityDbContext<User>, IdentityRole<int>, int>

//no exception but this code breaks

            var result = await _userManager.CreateAsync(user, model.Password);
            await _userManager.AddToRoleAsync(user, model.Role);
  1. public IQueryable FindAll() { var allUsers = (IQueryable)_socialNetworkDbContext.Users.AsQueryable(); if (allUsers == null) { throw new NoRecordFoundException(); } return allUsers;

//the same exception

3)

public IQueryable<User> FindAll()
        {
            var allUsers = (IQueryable<User>)(IEnumerable<User>)_socialNetworkDbContext.Users;
            if (allUsers == null)
            {
                throw new NoRecordFoundException();
            }
            return allUsers;

// the same exception (unable to cast to IEnumerable). Cast to ICollection (unable to cast to ICollection)

Would be very thankful for any advice!!!

Upvotes: 0

Views: 6411

Answers (4)

OG13
OG13

Reputation: 1

try First(); or FirstOrDefault();

Upvotes: 0

Zhi Lv
Zhi Lv

Reputation: 21353

From your code, it seems that the _socialNetworkDbContext.Users was stored the IdentityUser, instead of User model, right? So, after query data from the Users table, you could use the following code to convert the query result:

    public IQueryable<User> FindAll()
    { 
        var allUsers = _socialNetworkDbContext.Users.Select(c => new User()
        {
            UserName = c.UserName,
            Email = c.Email,
            //... other properties
        }).AsQueryable();
        if (allUsers == null)
        {
            throw new NoRecordFoundException();
        }
        return allUsers;
    }

Update

You can refer the following sample code:

Add an ApplicationUser class to customize the Identity User model:

public class ApplicationUser : IdentityUser<int>
{ 
    public string CustomTag { get; set; }
}

Use the ApplicationUser type as a generic argument for the context:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole<int>, int>
{
    public DbSet<ApplicationUser> ApplicationUsers { get; set; }
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

Update Pages/Shared/_LoginPartial.cshtml and replace IdentityUser with ApplicationUser:

@using Microsoft.AspNetCore.Identity
@using WebApp1.Areas.Identity.Data
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

Update the Startup.ConfigureServices and replace IdentityUser with ApplicationUser:

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDatabaseDeveloperPageExceptionFilter();

    services.AddIdentity<ApplicationUser, IdentityRole<int>>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultUI()
            .AddDefaultTokenProviders();

    services.AddControllersWithViews();
}

Then, enable migration and generate the database.

After creating new user, the AspNetUser table data as below:

enter image description here

Create a UserViewModel and add the required properties:

public class UserViewModel
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string Tag { get; set; }
}

Then, in the Controller, use the following code to query the user table:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly ApplicationDbContext _context;
    public HomeController(ILogger<HomeController> logger, ApplicationDbContext context)
    {
        _logger = logger;
        _context = context;
    }

    public IActionResult Index()
    {
        var result = FindAll();
        return View();
    }
    public IQueryable<UserViewModel> FindAll()
    {
        var allUsers = _context.Users.Select(c => new UserViewModel()
        {
            UserId = c.Id,
            UserName = c.UserName,
            Tag = c.CustomTag
        });
        //if (allUsers == null)
        //{
        //    throw new NoRecordFoundException();
        //}
        return allUsers;
    }

The result as below:

enter image description here

Upvotes: 1

juunas
juunas

Reputation: 58723

You should change your DbContext to use the actual user type:

public class SocialNetworkDbContext : IdentityDbContext<User, IdentityRole<int>, int>
{
}

If you have a class for the roles, you should use that as the generic type argument as well. This way you won't need any type casts.

Upvotes: 2

Meysam Bostak
Meysam Bostak

Reputation: 1

change your code :

    public async Task<List<User>> GetAllUsers()
        {
            var allUsers =  await _socialNetworkDbContext.Users.ToListAsync();
            if (allUsers == null)
            {
                throw new NoRecordFoundException();
            }
            return allUsers;
         }

Upvotes: -1

Related Questions