Entity Framework 告诉我支持上下文的模型已更改
Entity Framework telling me the model backing the context has changed
我有一个关于 Entity Framework 代码优先迁移的奇怪问题。几个月来,我一直在项目中使用 EF 和代码优先迁移,一切正常。我最近创建了一个新的迁移,当 运行 宁 Update-Database
我的数据库的恢复备份时,我收到此错误:
The model backing the context has changed since the database was
created. Consider using Code First Migrations to update the database
迁移执行如下操作:
public override void Up()
{
using (SomeDbContext ctx = new SomeDbContext())
{
//loop through table and update rows
foreach (SomeTable table in ctx.SomeTables)
table.SomeField = DoSomeCalculation(table.SomeField);
ctx.SaveChanges();
}
}
我没有使用 Sql() 函数,因为 DoSomeCalculation 必须在 C# 代码中完成。
通常当我得到这样的东西时意味着我已经以某种方式更新了我的模型并且忘记了创建迁移。然而这次并非如此。奇怪的是,错误甚至没有发生在我几天前创建的并且运行良好的迁移中。
我看了一个quite a few articles about this他们好像都说call
Database.SetInitializer<MyContext>(null);
这样做似乎可行,但我的理解是(based on this article) 这样做会消除 EF 确定数据库和模型何时不同步的能力。我不想那样做。我只想知道为什么它突然认为它们不同步。
我也尝试了 运行ning Add-Migration 只是为了看看它认为模型是否发生了变化,但它不会让我这样做,说明我有待处理的迁移到 运行。不错的第 22 条,微软。
对这里发生的事情有什么猜测吗?
我想知道上面列出的迁移使用 EntityFramework 是否可能是问题所在。似乎可能因为它不再是最新的迁移,当 EF 尝试创建一个 SomeDbContext 对象时,它会检查数据库(由于我们处于 运行ning 迁移的中间,它还没有完全更新) 针对我当前的代码模型,然后抛出 "context has changed" 错误。
这可能与您在迁移中使用 EF 有关。我不确定您实际上是如何管理它的,除非您设置了空数据库初始化程序。
如果您需要在迁移中更新数据,请使用 Sql
函数,例如
Sql("UPDATE SomeTable SET SomeField = 'Blah'");
您应该注意 Up()
方法在执行迁移时实际上并没有 运行ning,它只是用于设置迁移,然后 运行 .因此,尽管您可能认为您已经在使用 EF 的位上方的迁移中做了一些事情,但实际上还没有 运行。
如果您无法重构您的计算代码以便可以将其写入 SQL,那么您将需要使用一些机制而不是迁移到 运行 此更改。一种可能是在您的配置中使用 Seed
方法,但您需要注意,这不会跟踪更改是否为 运行。例如...
internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(MyContext context)
{
// Code here runs any time ANY migration is performed...
}
}
我尝试用常规 ADO.NET 代码替换 EntityFramework 代码,它似乎有效。这是它的样子:
public override void Up()
{
Dictionary<long, string> idToNewVal = new Dictionary<long, string>();
using (SqlConnection conn = new SqlConnection("..."))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT SomeID, SomeField FROM SomeTable", conn))
{
SqlDataReader reader = cmd.ExecuteReader();
//loop through all fields, calculating the new value and storing it with the row ID
while (reader.Read())
{
long id = Convert.ToInt64(reader["SomeID"]);
string initialValue = Convert.ToString(reader["SomeField"]);
idToNewVal[id] = DoSomeCalculation(initialValue);
}
}
}
//update each row with the new value
foreach (long id in idToNewVal.Keys)
{
string newVal = idToNewVal[id];
Sql(string.Format("UPDATE SomeTable SET SomeField = '{0}' WHERE SomeID = {1}", newVal, id));
}
}
我有一个关于 Entity Framework 代码优先迁移的奇怪问题。几个月来,我一直在项目中使用 EF 和代码优先迁移,一切正常。我最近创建了一个新的迁移,当 运行 宁 Update-Database
我的数据库的恢复备份时,我收到此错误:
The model backing the context has changed since the database was created. Consider using Code First Migrations to update the database
迁移执行如下操作:
public override void Up()
{
using (SomeDbContext ctx = new SomeDbContext())
{
//loop through table and update rows
foreach (SomeTable table in ctx.SomeTables)
table.SomeField = DoSomeCalculation(table.SomeField);
ctx.SaveChanges();
}
}
我没有使用 Sql() 函数,因为 DoSomeCalculation 必须在 C# 代码中完成。
通常当我得到这样的东西时意味着我已经以某种方式更新了我的模型并且忘记了创建迁移。然而这次并非如此。奇怪的是,错误甚至没有发生在我几天前创建的并且运行良好的迁移中。
我看了一个quite a few articles about this他们好像都说call
Database.SetInitializer<MyContext>(null);
这样做似乎可行,但我的理解是(based on this article) 这样做会消除 EF 确定数据库和模型何时不同步的能力。我不想那样做。我只想知道为什么它突然认为它们不同步。
我也尝试了 运行ning Add-Migration 只是为了看看它认为模型是否发生了变化,但它不会让我这样做,说明我有待处理的迁移到 运行。不错的第 22 条,微软。
对这里发生的事情有什么猜测吗?
我想知道上面列出的迁移使用 EntityFramework 是否可能是问题所在。似乎可能因为它不再是最新的迁移,当 EF 尝试创建一个 SomeDbContext 对象时,它会检查数据库(由于我们处于 运行ning 迁移的中间,它还没有完全更新) 针对我当前的代码模型,然后抛出 "context has changed" 错误。
这可能与您在迁移中使用 EF 有关。我不确定您实际上是如何管理它的,除非您设置了空数据库初始化程序。
如果您需要在迁移中更新数据,请使用 Sql
函数,例如
Sql("UPDATE SomeTable SET SomeField = 'Blah'");
您应该注意 Up()
方法在执行迁移时实际上并没有 运行ning,它只是用于设置迁移,然后 运行 .因此,尽管您可能认为您已经在使用 EF 的位上方的迁移中做了一些事情,但实际上还没有 运行。
如果您无法重构您的计算代码以便可以将其写入 SQL,那么您将需要使用一些机制而不是迁移到 运行 此更改。一种可能是在您的配置中使用 Seed
方法,但您需要注意,这不会跟踪更改是否为 运行。例如...
internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(MyContext context)
{
// Code here runs any time ANY migration is performed...
}
}
我尝试用常规 ADO.NET 代码替换 EntityFramework 代码,它似乎有效。这是它的样子:
public override void Up()
{
Dictionary<long, string> idToNewVal = new Dictionary<long, string>();
using (SqlConnection conn = new SqlConnection("..."))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT SomeID, SomeField FROM SomeTable", conn))
{
SqlDataReader reader = cmd.ExecuteReader();
//loop through all fields, calculating the new value and storing it with the row ID
while (reader.Read())
{
long id = Convert.ToInt64(reader["SomeID"]);
string initialValue = Convert.ToString(reader["SomeField"]);
idToNewVal[id] = DoSomeCalculation(initialValue);
}
}
}
//update each row with the new value
foreach (long id in idToNewVal.Keys)
{
string newVal = idToNewVal[id];
Sql(string.Format("UPDATE SomeTable SET SomeField = '{0}' WHERE SomeID = {1}", newVal, id));
}
}