指定正确的上下文以将身份添加到现有数据库中

问题描述 投票:0回答:2

之前也发过类似的问题(123),但情况不同

我有一个使用 EFCore 和一些现有实体的 .Net Core 7 应用程序。现在,其中的所有内容都已测试并正常工作,我想添加身份功能,然后将 AspNetUsers 链接到我现有的几个实体

目前没有身份表,也没有身份功能使用的任何类型的表。

使用 Microsoft 教程 在没有现有授权的情况下将 Scaffold Identity 引入 Razor 项目 我进入了需要指定数据库和用户上下文的步骤。

在查找文档失败后,我输入了数据库上下文,作为我的数据项目中使用的数据库上下文(下面的“EventFinderData” - 与我的 Web 应用程序不同的项目,但在同一解决方案中)。然后我创建了一个新的用户上下文...

脚手架完成后,当脚手架过程创建新的数据上下文时,我收到许多不明确的引用错误:

// This is a duplicate class of that within the EventFinderData project, which is already referenced within my web app
public class EventFinderContext : IdentityDbContext<EventFinderWebAppRazorUser> 
{
    public EventFinderContext(DbContextOptions<EventFinderContext> 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);
    }
}

我尝试创建两个类

partial
,但是当我添加迁移时,我得到:

发现多个 DbContext。指定使用哪一个。使用 PowerShell 命令的“-Context”参数和“--context” dotnet 命令的参数。

一些专家似乎建议开始一个已经包含身份的新项目,并从那里开始构建,但这将是一项艰巨的工作。

  1. 为了让这个脚手架流程融入到我现有的 EFCore 逻辑中,我需要修改什么?
  2. 身份是否应该使用专用(单独)上下文?鉴于表需要身份实体和我现有实体之间的关系,这似乎不直观。

更新

根据建议,以下是添加身份功能后我得到的三个类:

数据项目(包含实体和迁移):

EventFinderContext.cs

namespace EventFinderData
{
    public class EventFinderContext : DbContext
    {
        public DbSet<EventItem> EventItems { get; set; }
        public DbSet<EventCategory> EventCategories { get; set; }

        public EventFinderContext(DbContextOptions<EventFinderContext> options) : base(options) 
        {
        }

    }
}

Web 应用程序项目 - 由 VS/Identity 创建的类

区域\身份\数据\EventFinderWebAppRazorContext.cs

namespace EventFinderWebAppRazor.Data;
public class EventFinderWebAppRazorContext : IdentityDbContext<EventFinderWebAppRazorUser>
{
    public EventFinderWebAppRazorContext(DbContextOptions<EventFinderWebAppRazorContext> options)
        : base(options)
    {
    }

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

区域\身份\数据\EventFinderWebAppRazorUser.cs

namespace EventFinderWebAppRazor.Areas.Identity.Data;

public class EventFinderWebAppRazorUser : IdentityUser
{
}

程序.cs

builder.Services.AddDbContextFactory<EventFinderContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("EventFinderConnString"), 
        ss => ss.UseNetTopologySuite())
    .EnableSensitiveDataLogging());

builder.Services.AddDefaultIdentity<EventFinderWebAppRazorUser>(
    options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<EventFinderWebAppRazorContext>();
c# asp.net-core entity-framework-core asp.net-core-identity
2个回答
2
投票

不确定是否发生了变化(此处为.net6),但要将 dot net 身份框架添加到现有上下文中,您所要做的就是在将其添加到 IServiceCollection 时提供该上下文。

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
})
.AddEntityFrameworkStores<ApplicationDbContext>()

您需要更改 DbContext,以便它继承自

IdentityDbContext<ApplicationUser>

这只会提供所需的服务,而不会提供构建它时出现的不同视图和用户体验流程。因此无需登录/注销、密码重置、MFA 设置等...

我希望这会有所帮助。

更新

根据OP的更新,需要进行以下更新。

区域\身份\数据\EventFinderWebAppRazorUser.cs

将该类移至您的数据项目。它将成为您自己的实体模型的一部分。确保命名空间也已更新。虽然这并不是真正必要的,但是将所有实体都放在同一个命名空间中是很好的。

区域\身份\数据\EventFinderWebAppRazorContext.cs

删除该文件/类。这是脚手架过程创建的额外上下文,但由于我们想使用自己的上下文,所以不需要它。

EventFinderContext.cs

像下面一样更新这个类。

namespace EventFinderData
{
    public class EventFinderContext : IdentityDbContext<EventFinderWebAppRazorUser>
    {
        public DbSet<EventItem> EventItems { get; set; }
        public DbSet<EventCategory> EventCategories { get; set; }

        public EventFinderContext(DbContextOptions<EventFinderContext> options) : base(options) 
        {
        }

    }
}

程序.cs

如下更新此文件。并确保通过更新 usings 来解决所有类型。

builder.Services.AddDbContextFactory<EventFinderContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("EventFinderConnString"), 
        ss => ss.UseNetTopologySuite())
    .EnableSensitiveDataLogging());

builder.Services.AddDefaultIdentity<EventFinderWebAppRazorUser>(
    options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<EventFinderData.EventFinderContext>();

0
投票
builder.Services.AddIdentity<AppUser, IdentityRole>(opt => 
        {
            opt.Password.RequireNonAlphanumeric = false;
            opt.Password.RequiredLength = 8;
            opt.Password.RequireDigit = true;
            opt.Password.RequireLowercase = true;
            opt.Password.RequireUppercase = true;

            opt.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(3);
            opt.Lockout.MaxFailedAccessAttempts = 3;

            opt.User.AllowedUserNameCharacters = default;
            opt.User.RequireUniqueEmail = true;

        }).AddEntityFrameworkStores<AppDbContext>().AddDefaultTokenProviders();
        builder.Services.ConfigureApplicationCookie(con => { con.LoginPath = $"/Admin/Account/Login/{con.ReturnUrlParameter}"; });
       
© www.soinside.com 2019 - 2024. All rights reserved.