Невозможно сохранить учетные записи пользователей после переименования таблиц идентификации в Asp.Net MVC Core App - PullRequest
1 голос
/ 27 марта 2019

Мне удалось настроить имена таблиц Identity и IdentityUser, как описано на этом форуме.Моя проблема в том, что я не могу сохранить учетные записи пользователей после этого, и я получаю ошибку ниже:

Невозможно использовать таблицу «Пользователи приложения» для типа сущности «Пользователи приложения», поскольку она используется для типа сущности ApplicationUser, и тамнет связи между их первичными ключами.

Я включил здесь демонстрационное приложение, которое можно загрузить с здесь

После настройки имен таблиц я добавилПосле миграции и обновления базы данных все эти операции были выполнены успешно, затем я использовал команду скаффолда dotnet ef dbcontext для импорта других таблиц базы данных.После этого я добавил еще одну миграцию, которая была неудачной, ef framework выдает ошибку ниже:

Невозможно использовать таблицу 'AppRole' для типа сущности 'AppRole', так как она используется для типа сущности 'IdentityRole'и нет связи между их первичными ключами.

Я сбросил миграции, удалил таблицу _migration и начал все заново, но не могу заставить ее работать.Поэтому я умоляю вас помочь мне в этом.

Это снимок DB-Context

protected override void OnModelCreating(ModelBuilder modelBuilder)

{
    base.OnModelCreating(modelBuilder);

    modelBuilder.HasAnnotation("ProductVersion", "2.2.3-servicing-35854");

    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    {
        var table = entityType.Relational().TableName;
        if (table.StartsWith("AspNet"))
        {
            entityType.Relational().TableName = table.Replace(table.Substring(0, 6), "App");
        }
    };

    modelBuilder.Entity<AppRoleClaims>(entity =>
    {
        entity.HasIndex(e => e.RoleId);

        entity.Property(e => e.RoleId).IsRequired();

        entity.HasOne(d => d.Role)
            .WithMany(p => p.AppRoleClaims)
            .HasForeignKey(d => d.RoleId);
    });

    modelBuilder.Entity<AppRoles>(entity =>
    {
        entity.HasIndex(e => e.NormalizedName)
            .HasName("RoleNameIndex")
            .IsUnique()
            .HasFilter("([NormalizedName] IS NOT NULL)");

        entity.Property(e => e.Id).ValueGeneratedNever();

        entity.Property(e => e.Name).HasMaxLength(256);

        entity.Property(e => e.NormalizedName).HasMaxLength(256);
    });

    modelBuilder.Entity<AppUserClaims>(entity =>
    {
        entity.HasIndex(e => e.UserId);

        entity.Property(e => e.UserId).IsRequired();

        entity.HasOne(d => d.User)
            .WithMany(p => p.AppUserClaims)
            .HasForeignKey(d => d.UserId);
    });

    modelBuilder.Entity<AppUserLogins>(entity =>
    {
        entity.HasKey(e => new { e.LoginProvider, e.ProviderKey });

        entity.HasIndex(e => e.UserId);

        entity.Property(e => e.LoginProvider).HasMaxLength(128);

        entity.Property(e => e.ProviderKey).HasMaxLength(128);

        entity.Property(e => e.UserId).IsRequired();

        entity.HasOne(d => d.User)
            .WithMany(p => p.AppUserLogins)
            .HasForeignKey(d => d.UserId);
    });

    modelBuilder.Entity<AppUserRoles>(entity =>
    {
        entity.HasKey(e => new { e.UserId, e.RoleId });

        entity.HasIndex(e => e.RoleId);

        entity.HasOne(d => d.Role)
            .WithMany(p => p.AppUserRoles)
            .HasForeignKey(d => d.RoleId);

        entity.HasOne(d => d.User)
            .WithMany(p => p.AppUserRoles)
            .HasForeignKey(d => d.UserId);
    });

    modelBuilder.Entity<AppUserTokens>(entity =>
    {
        entity.HasKey(e => new { e.UserId, e.LoginProvider, e.Name });

        entity.Property(e => e.LoginProvider).HasMaxLength(128);

        entity.Property(e => e.Name).HasMaxLength(128);

        entity.HasOne(d => d.User)
            .WithMany(p => p.AppUserTokens)
            .HasForeignKey(d => d.UserId);
    });

    modelBuilder.Entity<AppUsers>(entity =>
    {
        entity.HasIndex(e => e.NormalizedEmail)
            .HasName("EmailIndex");

        entity.HasIndex(e => e.NormalizedUserName)
            .HasName("UserNameIndex")
            .IsUnique()
            .HasFilter("([NormalizedUserName] IS NOT NULL)");

        entity.Property(e => e.Id).ValueGeneratedNever();

        entity.Property(e => e.Email).HasMaxLength(256);

        entity.Property(e => e.NormalizedEmail).HasMaxLength(256);

        entity.Property(e => e.NormalizedUserName).HasMaxLength(256);

        entity.Property(e => e.UserName).HasMaxLength(256);
    });
}

Ответы [ 2 ]

1 голос
/ 27 марта 2019

Добрый день, вот подробное руководство для тех, кто хочет использовать в первую очередь подход к базе данных с настраиваемыми таблицами удостоверений с использованием Asp.Net Core 2.2 и ef core.

Шаг 1 ==> Сначала создайте базу данных и добавьте все таблицы, связи и ограничения

шаг 2 ==> предполагая, что вы добавили все зависимости ef framework, перейдите в Visual Studio и создайте один класс с именем, например, ApplicationUser, который наследуется от IdentityUser, также добавьте туда настраиваемые поля.

шаг 3 ==> настройте класс контекста БД для использования ApplicationUser и сделайте то же самое в Startup.cs при регистрации службы AddDbContext , а также используйте OnModelCreating для настройки имен таблиц идентификации . Не забудьте вызвать base.OnModelCreating (modelBuilder)

шаг 4 ==> добавить миграцию и обновить базу данных, это создаст таблицы идентичности в нашей уже существующей БД.

шаг 5 ==> Перейдите в свою систему управления реляционными базами данных (RDBMS) и убедитесь, что ваши настроенные таблицы идентификаторов были добавлены. Если это так, перейдите к шагу 6, иначе устраните проблему, прежде чем продолжить

step 6 ==> Ошибка dotnet ef dbcontext scaffold "connectionstring" Microsoft.EntityFrameworkCore.SqlServer -o Models / Entities -f -c "TempDbContext" команда от powershell или эквивалентная ей команда менеджера пакетов консоль

шаг 7 ==> Очень важно : найдите все связанные с таблицей идентичности объекты, имена которых были настроены на шаге 3. Убедитесь, что все эти 7 объектов наследуются от идентификатора, указав их тип первичного ключа, например:

public partial class AppUsers : IdentityUser<string>{}
public partial class AppUserTokens : IdentityUserToken<string>{}
public partial class AppUserRoles : IdentityUserRole<string>{}
public partial class AppUserLogins : IdentityUserLogin<string>{}
public partial class AppUserClaims : IdentityUserClaim<string>{}
public partial class AppRoles : IdentityRole<string>{}
public partial class AppRoleClaims : IdentityRoleClaim<string>{}

После этого перейдите к исходному классу DBContext, который зарегистрирован в ConfigureServices в файле startup.cs, и измените сигнатуру класса на

public class ApplicationDbContext : IdentityDbContext<AppUsers, AppRoles, string, AppUserClaims, AppUserRoles, AppUserLogins, AppRoleClaims, AppUserTokens>

Шаг 8: скопируйте весь метод DbSet и все внутри OnModelCreating из временного TempDBContext , автоматически сгенерированного командой scaffold на шаге 6, и замените то, что имеется в исходном DBContext или Вы также можете сделать TempDBContext своим основным DBContext, но не забудьте обновить ConfigureServices.

шаг 9. Обновите все ссылки на ApplicationUser и установите для них указатель на AppUsers , скопируйте все настраиваемые поля из ApplicationUser в AppUsers причина этого заключается в том, что ApplicationUser не имеет справочной таблицы для сопоставления в базе данных, а AppUsers имеет.

шаг 10 ==> Обновить все ваши представления и частичные представления, введенные с помощью

@inject SignInManager<AppUsers> SignInManager
@inject UserManager<AppUsers> UserManager

для использования AppUsers из ApplicationUser особенно _LoginPartial.cshtml и все готово. Теперь вы можете добавить учетные записи пользователей следующим образом:

var user = new AppUsers
                {
                    Id = Guid.NewGuid().ToString(),
                    UserName = "example@gmail.com",
                    Email = "example@gmail.com",
                    PhoneNumber = "0123456789",
                };

                var result = await userManager.CreateAsync(user, "Ex@mple88@gmail.com");

Готово !!! Выполните некоторую очистку кода и удалите все файлы и код, который больше не нужен, вот как мне удалось заставить Identity работать с использованием имен пользовательских таблиц и подхода БД. Невыполнение следующих шагов приведет к ошибкам, которые я опубликовал, и многим другим. Спасибо за прочтение.

0 голосов
/ 27 марта 2019

Вы можете изменить имена таблиц, используя следующие:

base.OnModelCreating(builder);

builder.Entity<UserProfile>().ToTable("UserProfile");
builder.Entity<UserProfile>().Property(up => up.Id).HasColumnName("UserId");
builder.Entity<UserRole>().ToTable("Role").Property(ur => ur.Id).HasColumnName("RoleId");
builder.Entity<UserRole>().Property(ur => ur.Id).HasColumnName("UserRoleId");
builder.Entity<IdentityUserClaim<int>>().ToTable("UserClaim");
builder.Entity<IdentityUserRole<int>>().ToTable("UserRole").HasKey(k => new {k.RoleId, k.UserId});
builder.Entity<IdentityUserLogin<int>>().ToTable("UserLogin");
builder.Entity<IdentityRoleClaim<int>>().ToTable("RoleClaim");
builder.Entity<IdentityUserToken<int>>().ToTable("UserToken");

Ссылка: https://mitchelsellers.com/blogs/2017/09/05/taking-control-of-aspnet-identity-table-names

...