Augusto Henrique
Augusto Henrique

Reputation: 238

Identity User FK

I've an application in Asp.NET Core 3.1 MVC with EF Core and Identity.

I've two tables Calls and AspNetUsers. AspNetUsers has many Calls and one Call has one AspNetUsers.

The Calls table structure is okay, I think. But now I need to get Calls from AspNetUsers.

In CallsController I'm trying: IList<Call> calls = this.User.Calls; but no success.

I tried:

IList<Call> calls = this._context.Calls.Where(x => x.UserId == this._userManager.GetUserId(this.User)).ToList(); 

I've success. But do it is correct?

So, in application i've identity classes and an ApplicationUser like this:

public class ApplicationUser : IdentityUser
{
    public virtual IList<Call> Calls { get; set; }
}

And in Startup class in ConfigureServices method:

services.AddDefaultIdentity<ApplicationUser>(options => 
    options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

So, What's the better way to get Calls from AspNetUsers? Thanks!

Upvotes: 0

Views: 943

Answers (2)

fahirmdz
fahirmdz

Reputation: 17

ApplicationUser should be

    public class ApplicationUser : IdentityUser
    {
       public virtual ICollection<Call> Calls { get; set; }
    }

Call entity should be

 public class Call
 {
    public int ID { get; set; }

    //...

    public string ApplicationUserId { get; set; }
    [ForeignKey(nameof(ApplicationUserId))]
    public virtual ApplicationUser ApplicationUser { get; set; }
 }

and, of course, you should override the OnModeCreating method in your DbContext like this

 public class ApplicationDbContext: DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options){}

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Call>()
                        .HasOne(x => x.ApplicationUser)
                        .WithMany(x => x.Calls);
        }

        //...DbSets..

     }

and finally, load all your calls in Calls collection of ApplicationUser

  var user = await _context.ApplicationUsers.FindAsync(_userManager.GetUserId(this.User));

  await context.Entry(user)
      .Collection(x => x.Calls)
      .LoadAsync();

Now, you have all your calls loaded in Calls collection of the current user.

Upvotes: 0

Nan Yu
Nan Yu

Reputation: 27538

You can set ApplicationUser like :

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<Call> Calls { get; set; }
}

Call.cs:

public class Call
{
    public int ID { get; set; }

    public string name { get; set; }

    // other properties

    public string UserID { get; set; }
    [ForeignKey("UserID")]
    public virtual ApplicationUser ApplicationUser { get; set; }
}

In ApplicationDbContext , add :

public virtual DbSet<Call> Calls { get; set; } //add this line 
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
    : base(options)
{
}

Then you can query the current user's call by :

if (User.Identity.IsAuthenticated)
{
    var userID = User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
    var calls = _applicationDbContext.Users.Include(u => u.Calls).First(u => u.Id == userID).Calls.ToList();

    //or
    var callsa = _applicationDbContext.Calls.Where(p => p.UserID == userID).ToList();
}

Upvotes: 2

Related Questions