Nhận dạng nhiều loại người dùng - Thiết kế DbContext


8

Tôi đang cố gắng sử dụng gói Nhận dạng của .NET Core với nhiều lớp mở rộng IdentityUser<Guid>nhưng với một UserRolelớp duy nhất .

Tôi có nhiều lớp mở rộng UserStore<T>cho từng loại người dùng và một lớp duy nhất mở rộng RoleStore<UserRole>.

Sau đây là của tôi startup.cs:

services.AddIdentity<InternalUser, UserRole>(IdentityOptions)
    .AddDefaultTokenProviders()
    .AddUserStore<InternalUserStore>()
    .AddRoleStore<GenericUserRoleStore>();

services.AddIdentityCore<Contractor>(IdentityOptions)
    .AddRoles<UserRole>()
    .AddDefaultTokenProviders()
    .AddUserStore<ContractorUserStore>()
    .AddRoleStore<GenericUserRoleStore>();

services.AddIdentityCore<Homeowner>(IdentityOptions)
    .AddRoles<UserRole>()
    .AddDefaultTokenProviders()
    .AddUserStore<HomeownerUserStore>()
    .AddRoleStore<GenericUserRoleStore>();

Của tôi DbContextkhông mở rộng IdentityDbContext:

public sealed class EntityDbContext: DbContext { }

Tôi đã nhận được nhiều lỗi vì vậy tôi đã thêm vào sau đây DbContextnhưng tôi đã nhận xét nó:

public DbSet<IdentityUserClaim<Guid>> UserClaims { get; set; }

public DbSet<IdentityUserRole<Guid>> UserRoles { get; set; }

Tôi đang nhận được nhiều lỗi khác nhau:

xây dựng Lỗi trên Instance 'Dal.IdentityStores.I InternalalUserStore' cho PluginType IUserStore - và Instance 'RoleManager' cho PluginType Microsoft.AspNetCore.Identity.RoleManager 1[Models.Entities.Users.UserRole] - and Instance 'Dal.IdentityStores.GenericUserRoleStore' for PluginType Microsoft.AspNetCore.Identity.IRoleStore1 [Model.Entities.Users.User. PluginType Microsoft.AspNetCore.Identity.IRoleStore 1[Models.Entities.Users.UserRole] - and Instance 'Dal.IdentityStores.ContractorUserStore' for PluginType Microsoft.AspNetCore.Identity.IUserStore1 [Models.Entities.Contractors.Contractor] - và Instance 'UserClaimsPrincipalFactory' cho PluginType Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory 1[Models.Entities.Contractors.Contractor] - and Instance 'UserClaimsPrincipalFactory<Contractor, UserRole>' for PluginType Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory1 [Models.Entities.Contractors.Contractor] - và Instance 'UserManager' cho PluginType Microsoft.AspNetCore.Identity.UserManager 1[Models.Entities.Homeowners.Homeowner] - and Instance 'UserClaimsPrincipalFactory<Homeowner>' for PluginType Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory1 [Model.Entities.Homeowners.Homeowner]

Đây là liên kết đến repo của tôi


Vì vậy, câu hỏi của bạn là gì?
Vano Maisuradze

Mã của tôi không hoạt động. Tôi đang nhận được lỗi trên. Làm cách nào tôi có thể sửa nó theo cách sử dụng nhiều loại như một "Người dùng".
Node.JS

Tôi đã nhân bản repo của bạn và nó hoạt động với tôi, vì vậy có lẽ đó là vấn đề môi trường của bạn.
Vano Maisuradze

1
@VanoMaisuradze Hãy thử tạo người dùng và đăng nhập. Bạn sẽ thấy vấn đề. Có một bộ điều khiển để đăng ký / đăng nhập
Node.JS

1
Có tôi đã làm. Cảm ơn bạn
Node.JS

Câu trả lời:


2

Tôi đã tái tạo vấn đề của bạn và dưới đây là một giải pháp cho vấn đề đó, nhưng tôi sẽ suy nghĩ lại về việc tạo nhiều bảng cho các vai trò người dùng khác nhau.

Đây là hai lý do chính chống lại nhiều bảng người dùng:

  1. Khi bạn muốn tìm người dùng theo id (Giả sử bạn không biết vai trò), bạn sẽ cần chạy nhiều truy vấn đối với các bảng khác nhau, điều này làm giảm hiệu suất và tăng độ phức tạp trong mã.
  2. Nó cũng có thể làm tăng độ phức tạp của cơ sở dữ liệu, bởi vì bạn sẽ cần đặt nhiều khóa ngoại cho các bảng khác.

Trong trường hợp bạn vẫn muốn có nhiều bảng cho các vai trò người dùng khác nhau, đây là một chút "hack". Bạn chỉ cần ghi đè phương thức OnModelCreating và định cấu hình các thực thể:

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

        builder.Entity<Contractor>(b =>
        {
            b.HasMany<IdentityUserRole<Guid>>().WithOne().HasForeignKey(ur => ur.UserId).IsRequired();
        });

        builder.Entity<UserRole>(b =>
        {
            b.HasKey(r => r.Id);
            b.HasIndex(r => r.NormalizedName).HasName("RoleNameIndex").IsUnique();
            b.ToTable("AspNetRoles");
            b.Property(r => r.ConcurrencyStamp).IsConcurrencyToken();

            b.Property(u => u.Name).HasMaxLength(256);
            b.Property(u => u.NormalizedName).HasMaxLength(256);

            b.HasMany<IdentityUserRole<Guid>>().WithOne().HasForeignKey(ur => ur.RoleId).IsRequired();
            b.HasMany<IdentityRoleClaim<Guid>>().WithOne().HasForeignKey(rc => rc.RoleId).IsRequired();
        });

        builder.Entity<IdentityRoleClaim<Guid>>(b =>
        {
            b.HasKey(rc => rc.Id);
            b.ToTable("AspNetRoleClaims");
        });

        builder.Entity<IdentityUserRole<Guid>>(b =>
        {
            b.HasKey(r => new { r.UserId, r.RoleId });
            b.ToTable("AspNetUserRoles");
        });

        builder.Entity<UserRole>().ToTable("Roles");
        builder.Entity<IdentityUserRole<Guid>>().ToTable("UserRoles");
        builder.Entity<IdentityRoleClaim<Guid>>().ToTable("RoleClaims");
        builder.Entity<IdentityUserClaim<Guid>>().ToTable("UserClaims");
    }

Sau đó, bạn sẽ có thể đăng nhập.


0

Dựa trên các yêu cầu mà OP đã giải thích trong các bình luận và OP nói rằng anh ấy / cô ấy không có kinh nghiệm thiết kế cơ sở dữ liệu, tôi sẽ cố gắng đưa ra một câu trả lời hy vọng sẽ giúp cuộc sống phát triển phần mềm và dự án của OP dễ dàng hơn:

Trước hết, bạn muốn có một bảng "Người dùng":

|---------------------|------------------|------------------|
|      FirstName      |     LastName     |       Role       |
|---------------------|------------------|------------------|
|          Joe        |       Black      |     Contractor   |
|---------------------|------------------|------------------|

Bạn không có yêu cầu đối với nhiều bảng Người dùng cho dự án, cũng như bất kỳ sản phẩm phần mềm hoặc dự án nào cũng yêu cầu một điều như vậy nói chung. Khi / NẾU Bảng người dùng chia tỷ lệ thành N hàng tỷ bản ghi, thì nó sẽ được phân chia thành các phân vùng để thực hiện và / hoặc không chuẩn hóa để đọc so với ghi, nhưng nó vẫn sẽ là một bảng trong nhiều thiết kế hệ thống phần mềm phức tạp.

Bạn nói:

Làm cách nào tôi có thể có siêu dữ liệu người dùng khác nhau cho các loại người dùng khác nhau? Nhà thầu có tài sản riêng, chủ nhà có bộ tài sản riêng, v.v. Tôi không muốn có một cái bàn khổng lồ với tất cả các thuộc tính có thể

Một mối quan tâm của bạn là bạn không kết thúc với một cái bàn khổng lồ. Nói tóm lại, đây không phải là mối quan tâm của bạn. Bạn chưa có một bảng khổng lồ và nếu bạn đã thêm 30 cột ("thuộc tính" như bạn đã nói) thì đó sẽ không phải là một bảng khổng lồ.

Tạo một bảng người dùng. Thêm các cột nullable cho các thuộc tính nhà thầu cụ thể và các cột nullable cho các thuộc tính chủ nhà cụ thể. Làm cho các cột Không Null khi thuộc tính áp dụng cho tất cả người dùng.

Một cột sẽ áp dụng cho tất cả người dùng là cột Vai trò cho Người dùng của bạn, vì vậy bạn có một cột Không thể gọi là "Vai trò"

Lưu ý, nếu bạn đang sử dụng cơ sở dữ liệu quan hệ, bạn không cần tạo bảng Vai trò chứa các bản ghi hàng Vai trò. Bạn có thể làm điều này và người hướng dẫn khóa học của bạn có thể mong đợi nó nhưng bạn cũng có thể tạo một lớp chuỗi const hoặc enum trong phần phụ trợ của bạn đại diện cho các Vai trò có thể và đó là một hình thức kiên trì cung cấp tính toàn vẹn cho các vai trò đó. Tôi đề cập đến điều này bởi vì đây là một lĩnh vực mà các nhà phát triển nhanh chóng đi sâu vào tính toàn vẹn tham chiếu với thiết kế cơ sở dữ liệu quan hệ.


1
Xin lỗi, nhưng câu trả lời của bạn là một gợi ý, mà tôi đã thực hiện. Điều này không trực tiếp trả lời câu hỏi của OP. Ngoài ra việc tạo các cột nullable có thể không phải là một giải pháp tốt. Ví dụ: Sử dụng Json có thể sạch hơn nhiều.
Vano Maisuradze

Không, nó là một chút nhiều hơn một gợi ý, đó là một cách đúng đắn để tiếp cận và thực hiện các giải pháp.
Brian Ogden
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.