gpt4 book ai didi

c# - EF 6 CodeFirst 添加迁移脚手架并生成不存在的更改

转载 作者:太空宇宙 更新时间:2023-11-03 17:00:14 26 4
gpt4 key购买 nike

我在当前的项目中使用 EF Migrations 有一段时间了,一切都很好,直到今天,情况如下:

  1. 我做了一个小改动,添加了一个字符串属性
  2. 我调用了一个 API 方法并收到错误消息,指出模型发生了变化
  3. 我运行了命令“Add-Migration MigrationXYZ”
  4. 使用未发生的额外更改创建新迁移

我运行了“Add-Migration MigrationXYZ -Force”以确保它不是一回事,我删除了数据库,重新启动了 VS(2015),但都一样

另一个问题是,即使我按照脚手架完成的方式应用迁移,仍然会返回错误“无法更新数据库以匹配当前模型,因为存在未决更改...”

在查看这些更改后,除了一个之外,其他所有更改都是关于具有 [Required] 属性的字符串属性,并且脚手架需要使其可为空,下面是一个示例。

public partial class MigrationXYZ: DbMigration
{
public override void Up()
{
AddColumn("dbo.Foos", "NewProperty", c => c.String());//<-- Expected Change
AlterColumn("dbo.Bars", "Name", c => c.String());//<-- Unexpected Change
}

public override void Down()
{
AlterColumn("dbo.Bars", "Name", c => c.String(nullable: false));//<-- Unexpected Change
DropColumn("dbo.Foos", "NewProperty");//<-- Expected Change
}
}

public class Bar
{
//This was not touched in ages, some even before adding the first migration
[Required]
public string Name { get; set; }
}

现在我卡住了,不知道如何解决这个......迁移状态中的损坏

编辑

我一直在尝试调试 Add-Migration 命令以了解为什么 EF 看到的模型与实际不同,但是当您具有 Identity 这样的依赖项时,使用 EF 源是不可能的需要签名的 DLL 才能工作。

然而,额外的研究让我找到了 answer here这导致 this blog post通过 @trailmax 和解密迁移哈希的代码,并在 EF 源中进行一些搜索,我制作了一个小应用程序来提取当前模型和上一个迁移模型以进行并排比较。

在 XML 中获取当前模型表示的代码

//Extracted from EF Source Code
public static class DbContextExtensions
{
public static XDocument GetModel(this DbContext context)
{
return GetModel(w => EdmxWriter.WriteEdmx(context, w));
}

public static XDocument GetModel(Action<XmlWriter> writeXml)
{
using (var memoryStream = new MemoryStream())
{
using (var xmlWriter = XmlWriter.Create(
memoryStream, new XmlWriterSettings
{
Indent = true
}))
{
writeXml(xmlWriter);
}

memoryStream.Position = 0;

return XDocument.Load(memoryStream);
}
}
}

//In Program.cs
using (var db = new DbContext())
{
var model = db.GetModel();
using (var streamWriter = new StreamWriter(@"D:\Current.xml"))
{
streamWriter.Write(model);
}
}

从 XML 迁移中提取模型的代码

//Code from Trailmax Tech Blog
public class MigrationDecompressor
{
public string ConnectionString { get; set; }

public String DecompressMigrationFromSource(IMigrationMetadata migration)
{
var target = migration.Target;
var xmlDoc = Decompress(Convert.FromBase64String(target));
return xmlDoc.ToString();
}

public String DecompressDatabaseMigration(String migrationName)
{
var sqlToExecute = String.Format("select model from __MigrationHistory where migrationId like '%{0}'", migrationName);

using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();

var command = new SqlCommand(sqlToExecute, connection);

var reader = command.ExecuteReader();
if (!reader.HasRows)
{
throw new Exception("Now Rows to display. Probably migration name is incorrect");
}

while (reader.Read())
{
var model = (byte[])reader["model"];
var decompressed = Decompress(model);
return decompressed.ToString();
}
}

throw new Exception("Something went wrong. You should not get here");
}

/// <summary>
/// Stealing decomposer from EF itself:
/// http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework/Migrations/Edm/ModelCompressor.cs
/// </summary>
private XDocument Decompress(byte[] bytes)
{
using (var memoryStream = new MemoryStream(bytes))
{
using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
{
return XDocument.Load(gzipStream);
}
}
}
}

//Inside Program.cs

var decompresser = new MigrationDecompressor
{
ConnectionString = "<connection string>"
};

var databaseSchemaRecord = decompresser.DecompressDatabaseMigration("<migration name>");
using (var streamWriter = new StreamWriter(@"D:\LastMigration.xml"))
{
streamWriter.Write(databaseSchemaRecord);
}

不幸的是,我仍然找不到问题,模型与上次迁移散列的模型之间的唯一区别是添加属性的预期变化,没有出现意外变化,同样在运行 EF 建议的迁移之后, 然后将当前模型与建议的迁移进行比较,模型仍然不匹配更改,应该不为空的在模型中仍然不为空,而建议的迁移将其显示为可为空。

出现预期的变化

<Property Name="NewProperty" Type="String" MaxLength="Max" FixedLength="false" Unicode="true" />
.
.
.
<ScalarProperty Name="NewProperty" ColumnName="NewProperty" />
.
.
.
<Property Name="NewProperty" Type="nvarchar(max)" Nullable="true" />

最佳答案

尝试使用

将您的数据库回滚到以前的数据库之一

更新数据库-targetMigration "nameofpreviousmigration"

(您可能需要在运行上述命令之前运行 update-database 我不确定)

然后删除你的新迁移,创建一个全新的迁移并运行

更新数据库

希望这会解决它认为有额外迁移的问题

另一种可能不是最好的解决方案是手动编辑迁移并删除意外部分

关于c# - EF 6 CodeFirst 添加迁移脚手架并生成不存在的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39022877/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com