I am building an ASP.NET Core 8.0 Blazor app in which I need data sets which are the results of tables with a join on ASP.NET users. For the first case I have chosen to use a View in my database
CREATE VIEW vwGuardianList
AS
SELECT
Users.Id AS UserId,
Users.FirstName, Users.LastName,
Users.Email,
Users.PhoneNumber,
g.FirstGuardianAddress1, g.FirstGuardianAddress2,
g.FirstGuardianCity, g.FirstGuardianPostcode,
g.FirstGuardianRelationship, g.FirstGuardianAgreed,
g.FirstGuardianAgeedDate,
g.SecondGuardianFirstName, g.SecondGuardianLastName,
g.SecondGuardianEmail, g.SecondGuardianPhone,
g.SecondGuardianAddress1 AS SecondAddress1,
g.SecondGuardianAddress2 AS SecondAddress2,
g.SecondGuardianCity, g.SecondGuardianPostcode,
g.SecondGuardianRelationship,
g.SecondGuardianAgreed, g.SecondGuardianAgeedDate,
g.Id as GuardianId
FROM
Guardians g
INNER JOIN
AspNetUsers Users ON g.FirstGuardianUserId = Users.Id
I have a data model class:
public class GuardianList
{
[Key]
public string? UserId { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Email { get; set; }
public string? PhoneNumber { get; set; }
public string? FirstGuardianAddress1 { get; set; }
public string? FirstGuardianAddress2 { get; set; }
public string? FirstGuardianCity { get; set; }
public string? FirstGuardianPostCode { get; set; }
public string? FirstGuardianRelationship { get; }
public bool FirstGuardianAgreed { get; set; }
public DateTime? FirstGuardianAgreedDate { get; set; }
public string? SecondGuardianFirstName { get; set; }
public string? SecondGuardianLastName { get; set; }
public string? SecondGuardianEmail { get; set; }
public string? SecondGuardianPhone { get; set; }
public string? SecondGuardianAddress1 { get; set; }
public string? SecondGuardianAddress2 { get; set; }
public string? SecondGuardianCity { get; set; }
public string? SecondGuardianPostCode { get; set; }
public string? SecondGuardianRelationship { get; }
public bool SecondGuardianAgreed { get; set; }
public DateTime? SecondGuardianAgreedDate { get; set; }
public string? GuardianId { get; set; }
}
And I have configured the ApplicationDBContext
as follows:
public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : IdentityDbContext<ApplicationUser>(options)
{
public DbSet<GuardianDetails> Guardians { get; set; }
public DbSet<MemberDetails> Members { get; set; }
public DbSet<VolunteerDetails> Volunteers { get; set; }
public DbSet<Teams> Teams { get; set; }
public DbSet<VolunteerTeams> VolunteersTeams { get; set; }
public DbSet<GuardianList> vwGuardianList { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<GuardianList>(c =>
{
c.HasAlternateKey("UserId");
c.ToView(nameof(vwGuardianList));
c.Property(x => x.UserId).HasColumnName("UserId");
});
}
}
The problem
The solution builds ok . However when a user attempts to login, the following exception occurs
An unhandled exception occurred while processing the request.
InvalidOperationException: The entity type 'IdentityUserLogin' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.
I have tried to add
The solution was provided by Ivan Stoev
The exception has nothing to do with the presented code. Except that you forgot to call base.OnModelCreating at the beginning of your override, thus base IdentityDbContext fluent configuration of the identity related entities has no effect. –