首页 > 解决方案 > 从 IdentityServer 实体中删除默认字段

问题描述

我一直在玩这个快速入门示例并且一直在尝试查看我可以自定义数据库多远(我有一个现有的数据库,我一直在尝试复制一半)。

到目前为止,我已经很幸运地摆弄了这个例子,添加新的字段/列组合很容易;但我现在想从实体中删除默认字段,并从数据库中删除它们的关联列。

所以,专注于IdentityUser对象,我已经定制了原件,ApplicationDbContext以反映我希望桌子的外观。我相信最初的定义如下:

modelBuilder.Entity("IdentityServer4AspNetIdentity.Models.ApplicationUser", b =>
{
    b.Property<string>("Id")
        .ValueGeneratedOnAdd();

    b.Property<int>("AccessFailedCount");

    b.Property<string>("ConcurrencyStamp")
        .IsConcurrencyToken();

    b.Property<string>("Email")
        .HasMaxLength(256);

    b.Property<bool>("EmailConfirmed");

    b.Property<bool>("LockoutEnabled");

    b.Property<DateTimeOffset?>("LockoutEnd");

    b.Property<string>("NormalizedEmail")
        .HasMaxLength(256);

    b.Property<string>("NormalizedUserName")
        .HasMaxLength(256);

    b.Property<string>("PasswordHash");

    b.Property<string>("PhoneNumber");

    b.Property<bool>("PhoneNumberConfirmed");

    b.Property<string>("SecurityStamp");

    b.Property<bool>("TwoFactorEnabled");

    b.Property<string>("UserName")
        .HasMaxLength(256);

    b.HasKey("Id");

    b.HasIndex("NormalizedEmail")
        .HasName("EmailIndex");

    b.HasIndex("NormalizedUserName")
        .IsUnique()
        .HasName("UserNameIndex");

    b.ToTable("AspNetUsers");
});

我的覆盖将结构定义为:

// "IdentityServer4AspNetIdentity.Models.ApplicationUser"
ModelBuilder.Entity<User>(E =>
{
    E.Property(P => P.Id)
        .HasColumnName("AccountId")
        .ValueGeneratedOnAdd();

    E.Property(P => P.ConcurrencyStamp)
        .HasMaxLength(512)
        .IsConcurrencyToken();

    E.Property(P => P.Email)
        .HasMaxLength(512)
        .IsRequired();

    E.Property(P => P.EmailConfirmed)
        .ValueGeneratedOnAdd();

    E.Property(P => P.NormalisedEmail)
        .HasMaxLength(512)
        .IsRequired();

    E.Property(P => P.NormalisedUserName)
        .HasMaxLength(256)
        .IsRequired();

    E.Property(P => P.PasswordHash);

    E.Property(P => P.SecurityStamp)
        .IsRequired();

    E.Property(P => P.TwoFactorEnabled)
        .ValueGeneratedOnAdd();

    E.Property(P => P.UserName)
        .HasMaxLength(256)
        .IsRequired();

    E.Property(P => P.Registered)
        .ValueGeneratedOnAdd();

    E.Property(P => P.LastVisit)
        .IsRequired();

    E.HasIndex(P => P.NormalisedEmail)
        .HasName("IX_Users_NormalisedEmail");

    E.HasIndex(P => P.NormalisedUserName)
        .IsUnique()
        .HasName("IX_Users_NormalisedUserName");

    E.ToTable("Users");
});

此覆盖对应于此User实体:

public class User : IdentityUser<int>
{
    public int AccountId
    {
        get => base.Id;
        set => base.Id = value;
    }
    public string NormalisedEmail
    {
        get => base.NormalizedEmail;
        set => base.NormalizedEmail = value;
    }
    public string NormalisedUserName
    {
        get => base.NormalizedUserName;
        set => base.NormalizedUserName = value;
    }
    public DateTime Registered { get; set; }
    public DateTime LastVisit { get; set; }

    public AccountDetail UserDetails { get; set; }
    public AccountLockout Lockout { get; set; }
    public PasswordReset PasswordResetRequested { get; set; }
    public Concierge ConciergeAccountFlag { get; set; }
    public NotValidated AccountValidatation { get; set; }

    public ICollection<UserRole> AssignedRoles { get; set; }
    public ICollection<UserClaim> ClaimsCollection { get; set; }
    public ICollection<Login> Logins { get; set; }
    public ICollection<LoginAttempt> LoginAttempts { get; set; }
    public ICollection<Token> TokenCollection { get; set; }
}

认为这足以重新定义对象并以我想要的结构化方式存储我想要的数据,但是我在尝试登录示例时看到以下异常:

An unhandled exception occurred while processing the request. SqlException: Invalid column name 'NormalizedUserName'. Invalid column name 'AccessFailedCount'. Invalid column name 'AccountValidatationAccountId'. Invalid column name 'ConciergeAccountFlagAccountId'. Invalid column name 'LockoutEnabled'. Invalid column name 'LockoutEnd'. Invalid column name 'NormalizedEmail'. Invalid column name 'NormalizedUserName'. Invalid column name 'PasswordResetRequestedAccountId'. Invalid column name 'PhoneNumber'. Invalid column name 'PhoneNumberConfirmed'.

我知道AccountValidatationAccountIdConciergeAccountFlagAccountId并且PasswordResetRequestedAccountId是我的外键,用于“NotValidated”、“Concierge”和“PasswordReset”实体(我将很快粘贴)但我不知道为什么它们被包含为列,并且为什么他们以他们的方式命名。

未验证:

ModelBuilder.Entity<NotValidated>(E =>
{
    E.Property(P => P.AccountId)
        .IsRequired()
        .ValueGeneratedNever();

    E.Property(P => P.ValidationKey)
        .IsRequired()
        .HasMaxLength(128)
        .ValueGeneratedNever();

    E.Property(P => P.Expires)
        .IsRequired()
        .ValueGeneratedOnAddOrUpdate();

    E.HasKey(P => P.AccountId);

    E.HasOne(P => P.Account)
        .WithOne()
        .HasForeignKey<User>(P => P.AccountId)
        .OnDelete(DeleteBehavior.Cascade)
        .HasConstraintName("FK_NotValidated_Users_AccountId");

    E.ToTable("NotValidated");
});

public class NotValidated
{
    public int AccountId { get; set; }
    public string ValidationKey { get; set; }
    public DateTime Expires { get; set; }

    public User Account { get; set; }
}

门房:

ModelBuilder.Entity<Concierge>(E =>
{
    E.Property(P => P.AccountId)
        .IsRequired()
        .ValueGeneratedNever();

    E.HasKey(P => P.AccountId);

    E.HasOne(P => P.Account)
        .WithOne()
        .HasForeignKey<User>(P => P.AccountId)
        .OnDelete(DeleteBehavior.Cascade)
    .HasConstraintName("FK_Concierge_Users_AccountId");

    E.ToTable("ConciergeMap");
});

public class Concierge
{
    public int AccountId { get; set; }

    public User Account { get; set; }
}

最后,密码重置:

ModelBuilder.Entity<PasswordReset>(E =>
{
    E.Property(P => P.AccountId)
        .IsRequired()
        .ValueGeneratedNever();

    E.Property(P => P.OneTimeKey)
        .IsRequired()
        .HasMaxLength(128)
        .ValueGeneratedNever();

    E.Property(P => P.Expires)
        .IsRequired()
        .ValueGeneratedNever();

    E.HasKey(P => P.AccountId);

    E.HasOne(P => P.Account)
        .WithOne()
        .HasForeignKey<User>(P => P.AccountId)
        .OnDelete(DeleteBehavior.Cascade)
        .HasConstraintName("FK_PasswordReset_Users_AccountId");

    E.ToTable("PasswordReset");
});

public class PasswordReset
{
    public int AccountId { get; set; }
    public string OneTimeKey { get; set; }
    public DateTime Expires { get; set; }

    public User Account { get; set; }
}

我确实设法通过尝试取消实现我不想要的字段来稍微减少列表,这会导致以下错误:

An unhandled exception occurred while processing the request. SqlException: Invalid column name 'NormalizedUserName'. Invalid column name 'AccountValidatationAccountId'. Invalid column name 'ConciergeAccountFlagAccountId'. Invalid column name 'NormalizedEmail'. Invalid column name 'NormalizedUserName'. Invalid column name 'PasswordResetRequestedAccountId'.

我通过在Users课程末尾添加这行代码来做到这一点,但我认为这很恶心&绝对不应该这样做:

public new int AccessFailedCount => throw new NotImplementedException();
public new int Id => throw new NotImplementedException("Use 'AccountId'.");
public new bool LockoutEnabled => throw new NotImplementedException();
public new DateTimeOffset? LockoutEnd => throw new NotImplementedException();
public new string NormalizedEmail => throw new NotImplementedException(
    "Use 'NormalisedEmail'."
);
public new string NormalizedUserName => throw new NotImplementedException(
    "Use 'NormalisedUserName'."
);
public new string PhoneNumber => throw new NotImplementedException();
public new bool PhoneNumberConfirmed => throw new NotImplementedException();

是否有人对我在指定和存储我的字段时出错的地方有任何指示?关于为什么要添加这些外键列的任何想法也将不胜感激。

标签: c#identityserver4

解决方案


推荐阅读