entity-framework-coreblazor-server-sidesql-view

Exception '''IdentityUserLogin<string>' requires a primary key to be defined."


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


Solution

  • 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. –