【问题标题】:EntityFrameWork Migration Asp.net Core 2.0EntityFrameWork 迁移 Asp.net Core 2.0
【发布时间】:2021-06-04 21:59:33
【问题描述】:

我有一个 Asp.Net core 2.0 项目,带有实体框架 Core 2.0Version。我有一个现有的数据库。现在进入 packagemanager 控制台窗口:Add-Migration 然后 Name:InitialMigration 之后 在我的项目中添加了迁移文件夹。然后我在包管理器控制台窗口中输入 Update-Database 注释。 '表已存在' 错误消息显示。因为该表已经在我的数据库中了。

我的要求是在我现有的模型中添加或删除属性时,该属性会在我现有的数据库中自动更新。我该怎么做?

【问题讨论】:

  • 您的迁移似乎丢失了一些轨道,导致它中断。之前创建了一个表,但模型快照(每次迁移后创建)与数据库不同步。在这种情况下,您可以手动调整它。在生产中,我们应该避免这样的错误,否则您可能会花费大量时间(要小心)手动处理数据库操作。

标签: asp.net-core entity-framework-core asp.net-core-mvc entity-framework-core-2.1 pomelo-entityframeworkcore-mysql


【解决方案1】:

您必须在重新创建迁移后删除数据库并更新数据库。但是如果你想更新你的数据库表,你可以创建另一个迁移并更新数据库而不删除现有的“InitialMigration”。

在您的实体中添加属性后,创建新的迁移,输出将如下所示;

public partial class UpdateDatabase : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<string>(
            name: "Description",
            table: "Category",
            type: "longtext CHARACTER SET utf8mb4",
            nullable: true);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropColumn(
            name: "Description",
            table: "Category");
    }
}

您可以使用 Update-Database 命令更新数据库;

  yourDbContextObject.Database.Migrate();

您应该会看到向数据库中的所有行添加了具有空值的新列。

或者,您可以在您的属性上添加自定义属性,如下所示;

/// <summary>
/// Attribute for adding default value in context level.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class MilvaDefaultValueAttribute : Attribute
{
    /// <summary>
    /// Specifies this property has a default value upon creation.
    /// </summary>
    /// <param name="defaultValue">The default value of the property.</param>
    public MilvaDefaultValueAttribute(object defaultValue)
    {
        DefaultValue = defaultValue;
    }

    /// <summary>
    /// Default value of tagged property.
    /// </summary>
    public object DefaultValue { get; private set; }
}


public class Category : BaseEntity
{
    [MilvaEncrypted]
    public string Name { get; set; }

    [MilvaDefaultValue("Default value added.")]
    public string Description { get; set; }

    public List<Todo> Todos { get; set; }
}

并在您的 DbContext 中覆盖 OnModelCreating 方法并在下面使用此扩展;

    public static void ConfigureDefaultValue(this ModelBuilder modelBuilder)
    {
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
            foreach (var property in entityType.GetProperties())
            {
                var memberInfo = property.PropertyInfo ?? (MemberInfo)property.FieldInfo;

                if (memberInfo == null) continue;

                var defaultValue = Attribute.GetCustomAttribute(memberInfo, typeof(MilvaDefaultValueAttribute)) as MilvaDefaultValueAttribute;

                if (defaultValue == null) continue;

                modelBuilder.Entity(entityType.ClrType).Property(property.Name).HasDefaultValue(defaultValue.DefaultValue);
            }
    }

my library 中的这个属性和扩展方法。由于没有时间,我无法添加文档,但代码中有文档,并且 github 项目中存在示例应用程序。

希望能帮到你。

【讨论】:

  • 我现有的数据库每个表都有多个记录。所以我无法删除我的数据库。如果我删除我的数据库,我会丢失我的数据。
  • @JuniorSoft 如果您有一个包含数据的现有数据库,那么“代码优先”方法将不起作用,因为它假定您首先在 C# 中创建模型,这些模型需要然后在数据库模式中复制。在这种情况下,您要查看的是dotnet ef dbcontext scaffold;例如,请参阅this page
  • 好的。因为我需要在我的模型上添加一个属性。到时候我会更新 EF 迁移该属性添加到数据库所以我问
  • 您可以通过在代码优先方法中创建新迁移来更新数据库。如果您的 InitialMigration 存在,则新的迁移将是不同的。 up 和 down 方法将只包含差异。但是您必须为新列添加默认值或列必须可以为空。我将针对这种方法编辑我的答案,请看一下。
【解决方案2】:

以下步骤可能对您有用!

Remove-Migration InitialMigration
Add-Migration name_of_new_migration
Update-Database -Force

如果上述步骤不起作用,请尝试以下步骤:

Add-Migration Initial -IgnoreChanges

这将创建一个空白的迁移脚本

Update-Database

这会将数据库更新为此迁移,但不会应用任何更改。您现在可以将更改添加到数据库上下文。完成后执行以下步骤。

Add-Migration name_of_new_migration

这将生成一个新的迁移脚本,其中包含您所做的更改。然后再次更新您的数据库。

Update-Database

【讨论】:

    猜你喜欢
    • 2018-03-01
    • 2019-11-12
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    • 2018-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多