我对Azure移动服务中使用Entity Frameworks代码优先迁移感到困惑。
我正在关注文章How to make data model changes to a .NET backend mobile service并获得Stack Overflow答案的其他帮助,并且还阅读了Code First Migrations和Code First Migrations in Team Environments并观看了Migrations - Under the Hood。
在Visual Studio 2015中,我创建了一个新的Azure移动服务,然后通过转到nuget包管理器控制台(PMC)并运行Enable-Migrations
来启用代码优先迁移。然后我构建并运行该项目。然后,为了创建数据库,我使用PMC命令Add-Migration Initial
创建初始迁移,并将其应用于PMC命令Update-Database -Verbose -TargetMigration Initial
。
此操作失败并显示错误消息
无法在表上创建多个聚簇索引 'MobileService1.TodoItems'。删除现有的聚簇索引 'PK_MobileService1.TodoItems'在创建另一个之前。
当我使用Verbose
标志时,我可以看到自动生成的SQL,并且确实将其插入查询并针对新建的数据库运行它会产生相同的错误,因为主键已经提供了聚簇索引。
CREATE TABLE [MobileService1].[TodoItems] (
[Id] [nvarchar](128) NOT NULL,
[Text] [nvarchar](max),
[Complete] [bit] NOT NULL,
[Version] rowversion NOT NULL,
[CreatedAt] [datetimeoffset](7) NOT NULL,
[UpdatedAt] [datetimeoffset](7),
[Deleted] [bit] NOT NULL,
CONSTRAINT [PK_MobileService1.TodoItems] PRIMARY KEY ([Id])
)
CREATE CLUSTERED INDEX [IX_CreatedAt] ON [MobileService1].[TodoItems]([CreatedAt])
但是the article警告我做出更改:将Database.SetInitializer(new MobileServiceInitializer());
中的MobileService1.WebApiConfig.Register
替换为
var migrator = new System.Data.Entity.Migrations.DbMigrator(new Migrations.Configuration());
migrator.Update();
但是在进行了更改之后,当我在PMC上运行Update-Database -Verbose -TargetMigration Initial
时,我得到完全相同的错误。
Dominique Alexandre对他的问题Running Azure Mobile Server project locally的评论中的另一个建议是用<{p}}代替Database.SetInitializer(new MobileServiceInitializer());
中的MobileService1.WebApiConfig.Register
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MobileServiceContext, Migrations.Configuration>());
但我又得到完全相同的错误。
我应该使用什么?是否有一种简单的方法通过Azure移动服务中使用的实体框架代码优先迁移?
答案 0 :(得分:11)
您看到的具体错误是由于EF假定主键也是聚簇索引,并且无法发出信号,表明情况并非如此。当您执行自动迁移时,事情会起作用,因为当应用程序启动时,Mobile Services / Apps会注册一个自定义的SqlGenerator来删除聚集索引(以及其他一些重要的事情)。默认情况下,迁移不会使用此自定义SqlGenerator。
但是,您可以通过在Migrations\Configuration.cs
文件中指定它来告诉您的迁移使用相同的SqlGenerator:
// Mobile Services namespace:
// using Microsoft.WindowsAzure.Mobile.Service.Tables
// Mobile Apps namespace:
// using Microsoft.Azure.Mobile.Server.Tables;
---<snip>---
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("System.Data.SqlClient", new EntityTableSqlGenerator());
}
试一试。生成的数据库应包括CreatedAt触发器和移动服务/应用程序所期望的其他特定于SQL的设置。如果您遇到问题,请告诉我,我可以进一步了解。
答案 1 :(得分:3)
在尝试了我能找到的每个解决方案后,我发现魔法位于这些行中(来自Quickstart项目)
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(
new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
"ServiceTableColumn", (property, attributes) => attributes.Single().ColumnType.ToString()));
base.OnModelCreating(modelBuilder);
}
(添加到您的上下文类)
这解决了群集错误问题。 (我使用的是Azure移动应用而非移动服务)
答案 2 :(得分:1)
我刚刚对此进行了测试,在PMC中使用更新数据库时也出现此错误。
我使用的是Azure移动应用,而不是服务,但它是相同的实体数据。
从空表开始,对我来说有用的只是初始迁移文件, Configuration.cs 和 MigrateDatabaseToLatestVersion 位。然后,您可以使用 F5 而不是更新数据库来运行应用程序。
它应该与你的种子一起创建你的模式。