Ядро EF обновляет исходные данные при каждой миграции без изменений

#c# #.net-core #entity-framework-core #entity-framework-migrations #ef-core-2.0

#c# #.net-core #entity-framework-core #entity-framework-миграции #ef-core-2.0

Вопрос:

Итак, я заполняю свою базу данных пользователями и ролями, подобными этому.

 public static void SeedUsers(this ModelBuilder modelBuilder)
    {
        var roles = new[]
        {
            new Role
            {
                Id = new Guid("5127599a-e956-4f5e-9385-1b8c6a74e4f1"),
                RoleName = "Customer"
            },
            new Role
            {
                Id = new Guid("8634c476-20fa-4391-b8f7-8713abf61af0"),
                RoleName = "Admin"
            }
        };

        // customer password
        byte[] customerPasswordHash = null;
        byte[] customerPasswordSalt = null;
        HashPassword("asd123", out customerPasswordHash, out customerPasswordSalt);

        // admin password
        byte[] adminPasswordHash = null;
        byte[] adminPasswordSalt = null;
        HashPassword("asd123", out adminPasswordHash, out adminPasswordSalt);
        var users = new[]
        {
            new Users()
            {
                Id = new Guid("3b86f5a2-1978-46e3-a0b6-edbb6b558efc"),
                FirstName = "John",
                LastName = "Doe",
                DepositedCash = 10000,
                Email = "john@doe.com",
                RoleId = roles[0].Id,
                PasswordHash = customerPasswordHash,
                PasswordSalt = customerPasswordSalt
            },
            new Users()
            {
                Id = new Guid("c643b944-53d9-4a0c-9922-3486558b9129"),
                FirstName = "Admin",
                LastName = "Admin",
                DepositedCash = 10000,
                Email = "admin@admin.com",
                RoleId = roles[1].Id,
                PasswordHash = adminPasswordHash,
                PasswordSalt = adminPasswordSalt
            }
        };

        modelBuilder.Entity<Role>()
            .HasData(roles);

        modelBuilder.Entity<Users>()
            .HasData(users);
    }

    private static void HashPassword(string password, out byte[] passwordHash, out byte[] passwordSalt)
    {
        using (var hmac = new System.Security.Cryptography.HMACSHA512(Encoding.UTF8.GetBytes("predefined key")))
        {
            passwordSalt = hmac.Key;
            passwordHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(password));
        }
    }
  

Я создаю миграцию и обновляю базу данных. Пока все хорошо.

После этого, когда я создаю другую тестовую миграцию, ничего не меняя, создается метод updateData с теми же данными. Все в Up и Down методах одинаковы.

 using System;
using Microsoft.EntityFrameworkCore.Migrations;

namespace Pizzeria.Data.Migrations
{
public partial class test : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.UpdateData(
            table: "Users",
            keyColumn: "Id",
            keyValue: new Guid("3b86f5a2-1978-46e3-a0b6-edbb6b558efc"),
            columns: new[] { "PasswordHash", "PasswordSalt" },
            values: new object[] { new byte[] { 211, 141, 232, 166, 77, 237, 128, 211, 121, 45, 47, 68, 211, 202, 162, 3, 39, 214, 212, 153, 4, 199, 223, 213, 43, 233, 224, 21, 107, 10, 62, 220, 105, 27, 254, 137, 16, 208, 56, 42, 254, 211, 154, 27, 60, 135, 197, 224, 148, 99, 232, 246, 220, 121, 113, 103, 42, 117, 172, 240, 134, 14, 188, 25 }, new byte[] { 112, 114, 101, 100, 101, 102, 105, 110, 101, 100, 32, 107, 101, 121 } });

        migrationBuilder.UpdateData(
            table: "Users",
            keyColumn: "Id",
            keyValue: new Guid("c643b944-53d9-4a0c-9922-3486558b9129"),
            columns: new[] { "PasswordHash", "PasswordSalt" },
            values: new object[] { new byte[] { 211, 141, 232, 166, 77, 237, 128, 211, 121, 45, 47, 68, 211, 202, 162, 3, 39, 214, 212, 153, 4, 199, 223, 213, 43, 233, 224, 21, 107, 10, 62, 220, 105, 27, 254, 137, 16, 208, 56, 42, 254, 211, 154, 27, 60, 135, 197, 224, 148, 99, 232, 246, 220, 121, 113, 103, 42, 117, 172, 240, 134, 14, 188, 25 }, new byte[] { 112, 114, 101, 100, 101, 102, 105, 110, 101, 100, 32, 107, 101, 121 } });
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.UpdateData(
            table: "Users",
            keyColumn: "Id",
            keyValue: new Guid("3b86f5a2-1978-46e3-a0b6-edbb6b558efc"),
            columns: new[] { "PasswordHash", "PasswordSalt" },
            values: new object[] { new byte[] { 211, 141, 232, 166, 77, 237, 128, 211, 121, 45, 47, 68, 211, 202, 162, 3, 39, 214, 212, 153, 4, 199, 223, 213, 43, 233, 224, 21, 107, 10, 62, 220, 105, 27, 254, 137, 16, 208, 56, 42, 254, 211, 154, 27, 60, 135, 197, 224, 148, 99, 232, 246, 220, 121, 113, 103, 42, 117, 172, 240, 134, 14, 188, 25 }, new byte[] { 112, 114, 101, 100, 101, 102, 105, 110, 101, 100, 32, 107, 101, 121 } });

        migrationBuilder.UpdateData(
            table: "Users",
            keyColumn: "Id",
            keyValue: new Guid("c643b944-53d9-4a0c-9922-3486558b9129"),
            columns: new[] { "PasswordHash", "PasswordSalt" },
            values: new object[] { new byte[] { 211, 141, 232, 166, 77, 237, 128, 211, 121, 45, 47, 68, 211, 202, 162, 3, 39, 214, 212, 153, 4, 199, 223, 213, 43, 233, 224, 21, 107, 10, 62, 220, 105, 27, 254, 137, 16, 208, 56, 42, 254, 211, 154, 27, 60, 135, 197, 224, 148, 99, 232, 246, 220, 121, 113, 103, 42, 117, 172, 240, 134, 14, 188, 25 }, new byte[] { 112, 114, 101, 100, 101, 102, 105, 110, 101, 100, 32, 107, 101, 121 } });
    }
}
}
  

Почему оно обновляет пользователей без каких-либо изменений? Чего мне не хватает?

Комментарии:

1. Я не тестировал это, но я думаю, что это из-за предварительно сгенерированной соли и пароля. При каждой новой ссылке или изменении свойств создается новая миграция.

2. В моем случае для свойства DateTime объекта было установлено значение Datetime.Now. Конечно, каждый раз это было по-разному…

3. @DiPi вы должны продвинуть этот комментарий в качестве ответа! Любые данные, добавляемые через HasData, должны быть надежно детерминированными и неизменными между миграциями, чтобы предотвратить их повторное появление в последующих миграциях.

Ответ №1:

Вы должны заполнять исходное значение, чтобы избежать этого :

 var users = new[]
        {
            new Users()
            {
                Id = new Guid("3b86f5a2-1978-46e3-a0b6-edbb6b558efc"),
                FirstName = "John",
                LastName = "Doe",
                DepositedCash = 10000,
                Email = "john@doe.com",
                RoleId = roles[0].Id,
                PasswordHash = new byte[] { 211, 141, 232, 166, 77, 237, 128, 211, 121, 45, 47, 68, 211, 202, 162, 3, 39, 214, 212, 153, 4, 199, 223, 213, 43, 233, 224, 21, 107, 10, 62, 220, 105, 27, 254, 137, 16, 208, 56, 42, 254, 211, 154, 27, 60, 135, 197, 224, 148, 99, 232, 246, 220, 121, 113, 103, 42, 117, 172, 240, 134, 14, 188, 25 },
                PasswordSalt = new byte[] { 112, 114, 101, 100, 101, 102, 105, 110, 101, 100, 32, 107, 101, 121 }
            },
            new Users()
            {
                Id = new Guid("c643b944-53d9-4a0c-9922-3486558b9129"),
                FirstName = "Admin",
                LastName = "Admin",
                DepositedCash = 10000,
                Email = "admin@admin.com",
                RoleId = roles[1].Id,
                PasswordHash = new byte[] { 211, 141, 232, 166, 77, 237, 128, 211, 121, 45, 47, 68, 211, 202, 162, 3, 39, 214, 212, 153, 4, 199, 223, 213, 43, 233, 224, 21, 107, 10, 62, 220, 105, 27, 254, 137, 16, 208, 56, 42, 254, 211, 154, 27, 60, 135, 197, 224, 148, 99, 232, 246, 220, 121, 113, 103, 42, 117, 172, 240, 134, 14, 188, 25 },
                PasswordSalt = new byte[] { 112, 114, 101, 100, 101, 102, 105, 110, 101, 100, 32, 107, 101, 121 }
            }
        };
  

Таким образом, ядро EF будет генерировать миграцию, зная, что это фиксированное значение, и не будет обновлять его при каждой миграции. Использование метода (HashPassword здесь) не позволяет ядру EF рассматривать его как исправленный.