ASP.NET Identity relationship - c#

I have a question.
I'm using ASP.NET CORE Identity(Individual User Accounts). It's already creating a separate database independent of my project. In my project, there are things I need to list that belong to the user. How can I do this ?
Database1-> ASP.NET CORE Identity Database (this database was created automatically)
Database2-> My App database
In Database2 Example Code;
public class Report:BaseModel
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime DateTime { get; set; }
public int UserId { get; set; } //(IT MUST BE ASP.NET USER TABLE)
public User User { get; set; } //(IT MUST BE ASP.NET USER TABLE)
}

First make sure that you have OnModelCreating on your DbContext class with base call
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
then add your class
public class Report : BaseModel
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime DateTime { get; set; }
public ApplicationUser User { get; set; }
}
then call migrations add-migration Report and Update-Database

Related

Entity Framework - Main table with two users with different name field, relation with a single field of foreign key

I'm using a EF with .Net Core 2.2. And I cannot figurated out how to solve the following problem:
I have the PQL and PM fields, these fields are the key of a user (Based in the table User).
So, How I can create two relations of two fields to the same field (In the secondary table) using EF...
Example, a requirement is to create a query to get all projects per user, where the user be the PM or the PQL...
The main table is:
public class ProjectHeader
{
[Key]
public int IdProjectHeader { get; set; }
[StringLength(200)]
public string ProjectName { get; set; }
[ForeignKey("FK_IdUser")]
[Column("IdUser")]
public int PM { get; set; }
[ForeignKey("FK_IdUser")]
[Column("IdUser")]
public int PQL { get; set; }
// NOT LINK WITH USER TABLE CORRECTLY
public User User { get; set; }
}
The User table is:
public class User
{
[Key]
public int IdUser { get; set; }
[Required]
[StringLength(100)]
public string UserName { get; set; }
[Required]
[StringLength(50)]
public string ShortName { get; set; }
[Required]
[StringLength(50)]
public string Email { get; set; }
}
A link to a question similar to this one. I would suggest you to research and use Entity Framework's Fluent API. Basically in your context class (that inherits DbContext class) you override the OnModelCreating method like so:
class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.HasOne(p => p.Blog)
.WithMany(b => b.Posts);
}
}
Inside you can configure some advanced relations for your database. You can look it up here.
I solved the problem... on main table I included:
[ForeignKey("PM")]
public User PmUser { get; set; }
[ForeignKey("PQL")]
public User PqlUser { get; set; }
...using the User Entity for both fields (Using a Foreign Key - Equal to the field on the main table)...
so, the PM match with idUser... and PQL match with idUser
Now... I have a circular reference when I tried to update the database using Code-first...
So, in the class public class ApplicationDbContext : DbContext I override the foreign keys:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ProjectHeader>().HasOne(m => m.PmUser).WithMany().OnDelete(DeleteBehavior.ClientSetNull);
modelBuilder.Entity<ProjectHeader>().HasOne(m => m.PqlUser).WithMany().OnDelete(DeleteBehavior.ClientSetNull);
}

How to add a new table with EF core

I have an existing database already that was created when i added Identity to the project. Now i wanna add more tables to the database and can't figure out how.
I have created a model for it:
public class Match
{
public Guid ID { get; set; }
public string HomeTeam { get; set; }
public string AwayTeam { get; set; }
public int FullTimeScore { get; set; }
public DateTime MatchStart { get; set; }
public int PrizePool { get; set; }
}
My context:
public class DynamicBettingUserContext : IdentityDbContext<IdentityUser>
{
public DynamicBettingUserContext(DbContextOptions<DynamicBettingUserContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}
What's the next steps?
You need to add the Match table in your DynamicBettingUserContext class like below. Then You need to add migration using Add-Migration <YourMigrationName> in Package Manager Console and finally, You have to run Update-Database command in PMC.
public virtual DbSet<Match> Match { get; set; }

.Net Core API with EF Core Code First and IdentityUser

I have an existing application that I am re-writing as .NET Core API with a ReactJS front-end. I am still in the API end, and I've run into a problem.
CODE
I have a BbUser.cs entity class with the following code:
public class BbUser : IdentityUser
{
public int Points { get; set; } = 0;
public string DisplayUsername { get; set; }
}
And I also have an Artist.cs entity class:
public class Artist
{
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string FirstName { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
[MaxLength(100)]
public string UrlFriendly { get; set; }
public string ImageUrl { get; set; }
public bool IsVerified { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public ICollection<Lyric> Lyrics { get; set; } = new List<Lyric>();
public string UserId { get; set; }
public BbUser User { get; set; }
}
I need a one-to-many relationship between BbUser and Artist. One user can submit many artists and lyrics ...etc. Simple stuff really.
PROBLEM
The application builds fine, but when I attempt to run it by hitting a controller that requires access to the Database, I get the following error:
The entity type 'IdentityUserLogin' requires a primary key to be defined.
I had this issues with regular EF Code First (not Core) and the fix for that, does not work here.
This model worked for me(compiled, and no exceptions at runtime) if I used next code in the DbContext class:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<BbUser>(b => b.ToTable("AspNetUsers"));
base.OnModelCreating(builder);
}
Without calling base.OnModelCreating(builder) I get the same error, because in this case context isn't applying the Identity related schema.
UPDATE:
Everything works fine for me as you can see from the screenshot below:
I have one more idea why you can have such an error. Did your BbContext inherit from DbContext class or IdentityDbContext<IdentityUser>? Because I got the same error that was on your screenshot if I used usual DbContext class.
In order to Idenity tables work fine you should use IdentityDbContext<IdentityUser>. Below the whole code for my working DbContext class
public class BbContext :IdentityDbContext<IdentityUser>
{
public BbContext(DbContextOptions options):base(options)
{
Database.EnsureCreated();
}
public DbSet<Artist> Artists { get; set; }
public DbSet<Lyric> Lyrics { get; set; }
public DbSet<Heart> Hearts { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<BbUser>(b => b.ToTable("AspNetUsers"));
builder.Entity<Heart>().HasKey(h => new {h.UserId, h.LyricId});
base.OnModelCreating(builder);
}
}
Please do try declaring a Guid property named Id, with both Get and Set on the IdentityUserLogin entity.
Another option is to declare a property and decorate it with [Key] attribute

How to Specify Entity Framework Core Table Mapping?

I've made a simple Entity Framework ASP Core Application that works but I do not know why:
I've made a context like this:
public class AstootContext : DbContext
{
public AstootContext(DbContextOptions<AstootContext> options)
: base(options)
{ }
public DbSet<Account> Accounts { get; set; }
public DbSet<User> Users { get; set; }
}
And I have two tables with models like this:
public class Account
{
public int Id { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
public DateTime Created { get; set; }
List<User> Users { get; set; }
}
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public DateTime Birthday { get; set; }
public Account Account { get; set; }
}
The interesting thing is that when I run my application it actually can pick up the data. It just seems weird because I have not specified any table mapping.
I'm assuming this just automaps because the specified tables are the same name.
My questions are:
How do I specify Table explicit table mapping in case I do not want my model names to be exactly the same as the DB?
How do I specify Custom Column Mapping.
Is there anything special I have to specify for Primary/Foreign Keys
edit
To clarify
Say I had a table in the DB MyAccounts and I wanted to map that to an entity Accounts.
Say I had a column password and I wanted that to map to a POCO property PasswordHash
To specify the name of the database table, you can use an attribute or the fluent API:
Using Attributes:
[Table("MyAccountsTable")]
public class Account
{
public string PasswordHash { get; set; }
}
Using Fluent API:
public class YourContext : DbContext
{
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Language>(entity => {
entity.ToTable("MyAccountsTable");
});
}
}
To name your columns manually, it's very similar and you can use an attribute or the fluent API:
Using Attributes:
public class Account
{
[Column("MyPasswordHashColumn")]
public string PasswordHash { get; set; }
}
Using Fluent API:
public class YourContext : DbContext
{
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Language>(x => x
.ToTable("MyAccountsTable")
.Property(entity => entity.PasswordHash)
.HasColumnName("MyPasswordHashColumn")
);
}
}

EF7 Incorrect configuration of the DBContext?

I am trying to figure out if my DBContext is set right. The Web Application I am trying to do is using ASP.NET 5, MVC6 and EF7.
It is connected to a DB that contains 3 tables (Comment, Review, Film). This is my model
WebDbModel.cs
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace WebExample.Models
{
public partial class Comment : IdentityUser
{
public string CommentId { get; set; }
public string ReviewId { get; set; }
public string Author { get; set; }
public System.DateTime Created { get; set; }
}
public partial class Review : IdentityUser
{
public string ReviewId { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string Creator { get; set; }
public string Status { get; set; }
public Nullable<System.DateTime> CreatedOn { get; set; }
}
public partial class Film : IdentityUser
{
public string ReviewId { get; set; }
public string FilmID { get; set; }
public string CommentId { get; set; }
public Nullable<int> CommentCount { get; set; }
public string FilmName { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual Review Review { get; set; }
}
}
Then, I have a class named
RegistrationDbContext.cs
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Data.Entity;
namespace WebExample.Models
{
public class ApplicationUser : IdentityUser
{
}
public class RegistrationDbContext : IdentityDbContext<ApplicationUser>
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
// Registration of the DB tables we are mapping.
public DbSet<Comment> Comments { get; set; }
public DbSet<Review> Reviews { get; set; }
public DbSet<Film> Films { get; set; }
}
}
I am wondering from here what is the use of public class ApplicationUser : IdentityUser
I am not sure if I should leave it there... If I remove it, then in my Startup.cs, the following code will complain...
// Add Identity services to the services container.
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<RegistrationDbContext>()
.AddDefaultTokenProviders();
So I don't know to what replace it given the fact I have Comment, Review and Film models...
So my question is... I guess I can delete the ApplicationUser class (auto generated when I created my solution) since this is not part of my model at all but... what should I put instead?
Not too sure if my question is right though, so apologies in advance! This seemed to be changed a lot compared to MVC5, EF6 and I couldn't fine too much documentation around IdentityDbContext
Also... am I missing something else in the RegistrationDbContext.cs class? The only extra thing I added was the registration of the tables... the rest came in the class by default.
Thanks!
There are a couple of issues here.
Firstly, IdentityUser is the representation of a logged-in user to your site, and is by default represented by the AspNetUsers table in the database, and stores all the usual stuff like email address, password, etc.
The provided ApplicationUser subclass is there in case you want to extend that in any way. Say for example you want to store the date of birth of your users:
public class ApplicationUser : IdentityUser
{
public DateTime DateOfBirth { get; set; }
}
That will tack on a DateOfBirth column to the AspNetUsers table.
In your case, if you don't want to extend the default user table in any way, you can just delete the ApplicationUser class and replace all references to it in your code to IdentityUser. For example:
// Add Identity services to the services container.
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<RegistrationDbContext>()
.AddDefaultTokenProviders();
Secondly, your models should not be inheriting from IdentityUser. That will just add all the fields from the AspNetUsers table to every model, which doesn't make sense, so remove : IdentityUser from your models.

Categories