将列/属性添加到 IdentityDbContext 中的 AspNetUserLogins/Logins

2023-12-24

是否可以添加列AspNetUserLogins表,或子类IdentityUserLogin类,以便身份框架能够正确使用该类?


这是一个答案,但我确信它最终不会是最好的答案:

这是可以做到的,但是很难看。

首先,您需要创建一个包含您将要使用的所有泛型的类,只是为了让您的生活更轻松。那些是:

[Table("AspNetUserRoles")]
public class StandardUserRole : IdentityUserRole<string>

[Table("AspNetRoles")]
public class StandardRole : IdentityRole<string, StandardUserRole>

[Table("AspNetUserLogins")]
public class LoginIdentity : IdentityUserLogin

(以上超类可以在Microsoft.AspNet.Identity.EntityFramework).

这将使以下通用定义变得更短,并且更难进入由于书写错误而无法编译的地方。

当您在这里时,也可以将这些添加到 DbContext,这通常不会让您可以使用它们:

public DbSet<LoginIdentity> LoginIdentities { get; set; }
public DbSet<StandardUserRole> UserRoles { get; set; }

现在,疯狂的事情来了:

public class Db :
    // Replace this with a custom implementation
    //IdentityDbContext<Visitor>,
    IdentityDbContext<Visitor, StandardRole, string, LoginIdentity,
        StandardUserRole, IdentityUserClaim>,

并且,访问者将需要自己进行调整以匹配此声明:

public class Visitor : IdentityUser<string, LoginIdentity, StandardUserRole,
    IdentityUserClaim>

这满足了模型(顺便说一句,出于迁移性能原因,最好将其放在自己的项目中)。但是,您仍然需要处理所有 Identity/OWIN 问题。

默认情况下,您会获得一个涉及 UserStore 的 ApplicationUserManager。它通常继承自 UserManager,但现在限制太多了 - 您需要稍微扩展它:

public class VisitorManager : UserManager<Visitor, string>
{
    public VisitorManager(IUserStore<Visitor, string> store)
        : base(store)

    {
    }

    public static VisitorManager Create(
        IdentityFactoryOptions<VisitorManager> options,
        IOwinContext context) 
    {
        var manager = new VisitorManager(new UserStore<Visitor,
            StandardRole, string, LoginIdentity, StandardUserRole,
            IdentityUserClaim>(context.Get<Db>()));

我警告过你要疯狂。登录管理器:

public class SignInManager : SignInManager<Visitor, string>
{
    public SignInManager(VisitorManager userManager,
        IAuthenticationManager authenticationManager)
        : base(userManager, authenticationManager)
    {
    }

    public override Task<ClaimsIdentity> CreateUserIdentityAsync(
        Visitor user)
    {
        return user.GenerateUserIdentityAsync((VisitorManager)UserManager);
    }

    public static SignInManager Create(
        IdentityFactoryOptions<SignInManager> options, IOwinContext context)
    {
        return new SignInManager(context.GetUserManager<VisitorManager>(),
            context.Authentication);
    }
}

这应该可以帮助你完成大部分肮脏的工作。不容易。但是,完成此操作后,您就获得了一个有效的实现,您可以在其中向登录表添加额外的字段!您现在可以扩展 OWIN Auth 内容来提供事件,并侦听新登录的创建。然后,您可以通过添加额外信息来回复这些信息。

在我们的例子中,目标是在单个用户/访问者帐户上跨多个电子邮件地址从多个 OpenId/OAuth 提供商(Google、Facebook 等)进行多次登录。该框架确实支持这一点,但是,它不会记录哪些电子邮件与哪些登录行相关联,这在将更多登录名与给定帐户合并时非常重要。

[Table("AspNetUserLogins")]
public class LoginIdentity : IdentityUserLogin
{
    /// <summary>
    /// The email address associated with this identity at this provider
    /// </summary>
    [MaxLength(300)]
    public string Email { get; set; }
}

要使整个事情正常运行,您还需要做更多的事情,但从上面的起点来看,它应该相对明显 - 但有一个例外,我将在这里指出。

通过迁移自UserManager<TVisitor> to UserManager<TVisitor, string>,您会悄悄地失去前者内置的 ID 生成功能。你需要自己模仿它。作为另一个陷阱,一路上你很可能会实现Visitor as IUser<string>。这样做将阻止您设置 Id 属性,因为它是只读的(无设置器)。您可以使用第二个接口来避免这种情况:

public interface IVisitor
{
    string Id { get; set; }
    string Uid { get; set; }
    string UserName { get; set; }
    string Email { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }
    ICollection<StandardUserRole> Roles { get; }
    ICollection<LoginIdentity> Logins { get; }
}

有了它,你就可以安全地设置 Id (即使在抽象类中):

public override Task<IdentityResult> CreateAsync(Visitor user)
{
    var guid = Guid.NewGuid();
    string id = guid.ToString();
    ((IVisitor)user).Id = id;
    return base.CreateAsync(user);
}

请记住对 CreateAsync(访问者用户,字符串密码)执行相同的操作。否则创建的用户会爆炸DbEntityValidationException投诉 ID 为必填字段。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将列/属性添加到 IdentityDbContext 中的 AspNetUserLogins/Logins 的相关文章

  • LINQ 到实体日期时间比较

    我在将 LINQ 中的日期与实体表达式进行比较时遇到问题 我想检查一下是否DateTime DateTime whole day 我想这样做 return context Events Any x gt x UserId id x Date
  • 实体框架 SaveChanges 错误详细信息

    保存更改时SaveChanges在数据上下文上有没有办法确定哪个实体导致错误 例如 有时我会忘记将日期分配给不可为空的日期字段并收到 无效日期范围 错误 但我没有得到有关它是由哪个实体或哪个字段引起的信息 我通常可以通过煞费苦心地检查我所有
  • 当绑定值为 null 时出现 WPF 日期选择器验证错误

    我有一个 WPF 应用程序 其中使用绑定到实体框架 带有 SQL Server 实体的日期字段的日期选择器 我将其绑定如下
  • 为什么 EF DataBase First 不使用 getdate()?

    我首先使用 EF 4 1 和数据库 示例表 CREATE TABLE dbo Product ID int IDENTITY 1 1 not null Title nvarchar 200 not null CreateDate datet
  • 使用 IQueryable 进行单元测试代码

    我被要求为某些功能编写一些单元测试 但坦率地说 我不太确定这样做的必要性或有用性对于这个特殊的一段代码 我绝不试图质疑单元测试的必要性或有用性 所讨论的代码非常简单并且被大量使用 基本上它是 Skip 和 Take 扩展方法的包装 在我看来
  • 从数据库加载而不使用代理类?

    在 Entity Framework 4 中 是否可以选择将一些查询加载到 POCO 中而不使用代理类 为了缓存该对象以供将来只读使用 我正在使用存储库 服务模式 我的意思是 var order orderService GetById 1
  • EF - 从自动迁移转向手动迁移

    结束了漫长的一天测试各种场景 我不必重新创建生产数据库 我们从 EF 开始 在开发过程中没有足够明智地从自动迁移转向命名迁移 现在 我正在尝试倒带时钟 并创建与生产数据库一致的初始迁移 是否可以将模型与迁移表中的自动迁移进行对齐 我应该创建
  • 使用经度和纬度查找给定距离内的所有附近客户

    我有一个包含客户经度和纬度的数据库 我有一个搜索表单 用户将在其中输入日志 纬度 距离下拉列表包含 50 英里 100 英里 当用户单击搜索时 我想编写一个 linq 查询从数据库中获取此距离半径内的所有客户 如何使用 C 和 linq 来
  • EF6 Code First 支持表值函数吗?

    是否可以在 EF6 Code First 中调用 TVF 我首先使用 EF6 数据库启动了一个新项目 EF 能够将 TVF 导入到模型中并调用它就好了 但是 对于我一直在处理的没有 RI 的大型只读数据库 更新模型变得非常耗时并且存在问题
  • 使用 lambda 对多列进行分组

    如何使用 lambda 对多列进行分组 我看到了如何使用 linq toEntity 执行此操作的示例 但我正在寻找 lambda 形式 var query source GroupBy x gt new x Column1 x Colum
  • Linq to Entities 中的动态 where 子句 (OR)

    在文中here https stackoverflow com questions 9122220 dynamic where clause in linq to entities我学习了如何使用 Linq 的延迟执行来构建动态查询 但查询
  • 如何使用 LINQ to Entities 调用带返回值的 Oracle 函数?

    我正在开发一个从 Oracle 11g 数据库访问数据的应用程序 我使用的是 EF4 并且使用 LINQ 访问数据 我遇到过一个场景 我需要调用存储在包中的函数 这个函数也有一个返回值 我已将此函数添加到实体数据模型中 但无法对其执行 添加
  • 我的 SQL 表设置为允许该列为 NULL,但是当我运行它时,它说它不能为 NULL。什么/为什么/如何?

    所以我在这里遇到了很奇怪的困境 我的 SQL 表设置为允许 ZipCode 列为空 如下所示 CREATE TABLE dbo Companies CompanyId BIGINT IDENTITY 1 1 NOT NULL PRIMARY
  • 播种多对多数据

    您好 我正在尝试为我的项目创建一些种子 但我在将多对多关系数据播种到数据库时遇到问题 My database看起来像这样 in 教师技能 教师ID and Skill ID当然是他们的表的外键 My seeder看起来像这样 protect
  • 实体框架:从模型生成数据库从模型存储中删除存储过程

    我正在使用带有 EF 4 模型的存储过程 为了实现这一目标 我将执行以下步骤 我通过从数据库更新并选择它来将存储过程添加到我的模型存储中 添加了函数导入以指向存储过程 存储过程返回连接多个表等的查询结果 因此在 返回集合 我指定的区域复合型
  • 使用实体框架从集合中删除项目

    我正在使用DDD 我有一个 Product 类 它是一个聚合根 public class Product IAggregateRoot public virtual ICollection
  • 实体框架 4 DB 优先依赖注入?

    我更喜欢创建自己的数据库 设置索引 唯一约束等 使用 edmx 实体框架设计器 从数据库生成域模型是轻而易举的事 现在我有兴趣使用依赖注入来设置一些存储库 我查看了 StackOverflow 上的一些文章和帖子 似乎重点关注代码优先方法
  • 运行更新数据库时出错

    我在运行时遇到以下错误Update Database Verbose 使用启动项目 WebApplication 使用 NuGet 项目 Web应用程序 指定 Verbose 标志来查看 SQL 应用于目标数据库的语句 目标数据库是 星冰乐
  • 处理与不同相关实体的一对多的正确模式

    我有一个 C 项目 我使用实体框架作为 ORM 我有一个User 可以向多家银行付款 每家银行都是一个独立的实体 并且每家银行都由不同的字段描述 问题是 一User可以没有或有很多不同的Banks 我不太确定如何对此进行建模 临时解决方案是
  • 为什么 EF Core 使用此存储过程总是返回 -1?

    我正在尝试对本地 2016 DB 使用 EF Core 最新版本 并且我得到 1每次都回来 我不知道我做错了什么 我知道它正在到达数据库 我查了一下 int returnCode dbContext Database ExecuteSqlC

随机推荐