Подтвердить что ты не робот

Первая ошибка миграции и инициализация кода

Я не уверен, как использовать первую функцию переноса кода. По моему мнению, он должен создать мою базу данных, если она уже не существует, и обновить ее до последней схемы в соответствии с файлами миграции. Но я борюсь с этим, потому что у меня всегда появляется много ошибок, и я не уверен, как правильно это использовать.

internal class Program
{
    private static void Main()
    {
        EntityFrameworkProfiler.Initialize();

        Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Migrations.Configuration>());

        using (var context = new MyContext())
        {
            var exists = context.Database.Exists();
            if (!exists)
            {
                context.Database.Create();
            }

            var element = context.Dummies.FirstOrDefault();
        }
    }
}

public class MyContext : DbContext
{
    public MyContext()
        : base(string.Format(@"DataSource=""{0}""", @"C:\Users\user\Desktop\MyContext.sdf"))
    {
    }

    public DbSet<Dummy> Dummies { get; set; }
}

internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(CodeFirstTest.MyContext context)
    {
    }
}

Используя Profiler Framework Profiler, я проверяю, какие операторы выполняются. Когда я запускаю программу без существующей базы данных, я получаю следующий вывод:

- оператор # 1 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- оператор # 2 WARN: System.Data.SqlServerCe.SqlCeException(0x80004005): Указанная таблица не существует. [__MigrationHistory]    в System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 hr)    в System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan()    в System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(поведение CommandBehavior, метод String, параметры ResultSetOptions)    в System.Data.SqlServerCe.SqlCeCommand.ExecuteReader(поведение CommandBehavior)    в System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteReader(поведение CommandBehavior)    в System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteDbDataReader(поведение CommandBehavior)    в HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledCommand.ExecuteDbDataReader(поведение CommandBehavior)

- оператор # 3 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- оператор # 4 WARN: System.Data.SqlServerCe.SqlCeException(0x80004005): Указанная таблица не существует. [__MigrationHistory]    в System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 hr)    в System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan()    в System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(поведение CommandBehavior, метод String, параметры ResultSetOptions)    в System.Data.SqlServerCe.SqlCeCommand.ExecuteReader(поведение CommandBehavior)    в System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteReader(поведение CommandBehavior)    в System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteDbDataReader(поведение CommandBehavior)    в HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledCommand.ExecuteDbDataReader(поведение CommandBehavior)

- утверждение # 5 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- оператор # 6 WARN: System.Data.SqlServerCe.SqlCeException(0x80004005): Указанная таблица не существует. [__MigrationHistory]    в System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 hr)    в System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan()    в System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(поведение CommandBehavior, метод String, параметры ResultSetOptions)    в System.Data.SqlServerCe.SqlCeCommand.ExecuteReader(поведение CommandBehavior)    в System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteReader(поведение CommandBehavior)    в System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteDbDataReader(поведение CommandBehavior)    в HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledCommand.ExecuteDbDataReader(поведение CommandBehavior)

- оператор # 7 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- оператор # 8 WARN: System.Data.SqlServerCe.SqlCeException(0x80004005): Указанная таблица не существует. [__MigrationHistory]    в System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 hr)    в System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan()    в System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(поведение CommandBehavior, метод String, параметры ResultSetOptions)    в System.Data.SqlServerCe.SqlCeCommand.ExecuteReader(поведение CommandBehavior)    в System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteReader(поведение CommandBehavior)    в System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteDbDataReader(поведение CommandBehavior)    в HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledCommand.ExecuteDbDataReader(поведение CommandBehavior)

- оператор # 9 начать транзакцию с уровнем изоляции: Serializable

- оператор # 10 CREATE TABLE [Dummies]   (      [Name] nvarchar NOT NULL,      CONSTRAINT [PK_Dummies] ПЕРВИЧНЫЙ КЛЮЧ ([Имя])   )

- оператор # 11 CREATE TABLE [ MigrationHistory]   (      [MigrationId] nvarchar NOT NULL,      [CreatedOn] [datetime] NOT NULL,      [Модель] [изображение] NOT NULL,      [ProductVersion] nvarchar NOT NULL,      CONSTRAINT [PK _MigrationHistory] ПЕРВИЧНЫЙ КЛЮЧ ([MigrationId])   )

- оператор № 12 INSERT INTO [__MigrationHistory]             ([MigrationId],              [Создано на],              [Модель],              [ProductVersion]) VALUES ('201207261524579_InitialCreate',              '2012-07-26T15: 24: 58,523', 0x1F8B080              , '4.3.1')

- оператор # 13 совершить транзакцию

- оператор # 14 SELECT TOP (1) [c]. [Name] AS [Name] FROM [Dummies] AS [c]

Как вы можете видеть, он пытается получить доступ к базе данных четыре раза, прежде чем она фактически создаст базу данных. Это не кажется правильным. Когда я запускаю приложение с существующей базой данных, он будет запрашивать базу данных 7 раз, прежде чем какой-либо из моих реальных запросов будет выполнен. Обратите внимание, что это происходит с context.Database.Create(), а не с .Exists().

Также метод семени моей конфигурации никогда не вызывается, но конструктор.

Все это кажется очень неправильным и запутанным. Я надеюсь, что кто-то может просветить меня, почему ошибки происходят так часто в начале и почему мой метод семени вообще не вызывается.

Я использую последние стабильные версии SqlServer compact и Entity Framework.

package id = "EntityFramework" version = "4.3.1" targetFramework = "net40"

package id = "Microsoft.SqlServer.Compact" version = "4.0.8854.2" targetFramework = "net40"

4b9b3361

Ответ 1

Кажется, есть много способов настроить сущность, и у каждого есть свое собственное преимущество над тем, что лучше. Все, что я могу предложить, это мое мнение, основанное на том, что мы стандартизировали в моей работе. Многие из них - предпочтение разработчика. Мои предпочтения, как правило, контролируют как можно больше, поэтому я всегда точно понимаю, что происходит и когда.

Автоматические миграции

Прежде всего, в то время как автоматические миграции могут быть удобными, но они вызывают много проблем, особенно по мере роста проекта и/или данных. На мой взгляд, любая коммерческая/производственная система должна иметь больше контроля, чем это. Мы всегда выключаем автоматические миграции для всех наших крупных проектов, устанавливая AutomaticMigrationsEnabled = false;. Мы выполняем наши миграции явно, когда хотим это сделать (на dev это находится в консоли диспетчера пакетов в visual studio, набрав Update-Database, и в процессе производства мы создали собственную небольшую утилиту миграции, которая просто называет переход на последний код явно, но ни один из них не является автоматическим).

@Террический ответ пугает меня как с автоматической миграцией, так и с потерей данных! Я не хочу быть тем парнем, который развертывает решение и вытирает некоторые важные данные из-за плохо выполненного изменения столбцов, что привело к потере данных. В качестве побочного примечания, когда мы явно выполняем миграцию в dev, я часто использую ключ -v для подробного вывода (Update-Database -v). Это позволяет увидеть исполняемый SQL и любые ошибки/предупреждения, если это необходимо.

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

Лично я удаляю инициализатор, у вас есть MigrateDatabaseToLatestVersion, и запускайте сам migrator именно тогда, когда захочу (либо через консоль менеджера пакетов, либо через свой собственный явный код где-нибудь).

Создание базы данных, если она не существует

Это поведение обеспечивается DatabaseInitializer (не самой EntityFramework). Инициализатор CreateDatabaseIfNotExists встроен в EntityFramework и по умолчанию в некоторых версиях. Однако, опять же, я не один из всех предполагаемых вещей поведения приложения. По-моему, я бы хотел немного контролировать.

Этот парень имеет пример пользовательского инициализатора базы данных, наследующего от встроенного CreateDatabaseIfNotExists. Но вы всегда можете просто создать свою собственную и реализовать любую точную логику, которую хотите увидеть (в том числе создание вашей базы данных). Опять же, это просто позволяет избежать неожиданного поведения. Мое личное предпочтение как разработчика - это тщательно контролировать этот материал, если только я не буду разбираться с макетом или тестовым проектом.

Супер простой пользовательский DatabaseInitializer без неожиданного поведения:

namespace MyProject.Data.DatabaseInitializers
{
    public class MyCustomDbInit<TContext> : IDatabaseInitializer<TContext>
        where TContext : DbContext
    {
        public void InitializeDatabase(TContext context)
        {
            // Create our database if it doesn't already exist.
            context.Database.CreateIfNotExists()

            // Do you want to migrate to latest in your initializer? Add code here!

            // Do you want to seed data in your initializer? Add code here!
        }
    }
}

Результаты

Если вы используете первый подход кода, отключите автоматическую миграцию и используйте собственный DatabaseInitializer, как указано выше, у вас будет очень хороший контроль над тем, что происходит и когда.

Мы используем эти стратегии на работе и имеем нулевые проблемы (хотя для решения этих проблем возникла определенная проблема). Надеюсь, вы найдете схожий успех!

Ответ 2

Я смог реплицировать вашу проблему с помощью SQL CE, а также сначала использовать код EF, используя код выше.

Странно, что когда я использовал ваш код как есть, в первый раз он работал отлично. Чтобы ваша проблема возникла, мне пришлось фактически удалить таблицу _MigrationHistory в моем .sdf файле.

Удалив файл .sdf(я понимаю, что это может быть не вариант в вашем случае, но я буду решать, что дальше). В следующий раз, когда он запустился, он создал таблицу миграции, но он все еще не работал совершенно правильно. Если вы заметили, на шаге 12 он, наконец, создает таблицу.

- оператор # 1 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [Dummies] AS [Extent1]) AS [GroupBy1]

- оператор # 2 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- statement # 3 WARN: System.Data.SqlServerCe.SqlCeException(0x80004005): Указанная таблица не существует. [__MigrationHistory ]

- оператор # 4 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- statement # 5 WARN: System.Data.SqlServerCe.SqlCeException(0x80004005): Указанная таблица не существует. [__MigrationHistory ]

- оператор # 6 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- statement # 7 WARN: System.Data.SqlServerCe.SqlCeException(0x80004005): Указанная таблица не существует. [__MigrationHistory ]

- оператор # 8 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- statement # 9 WARN: System.Data.SqlServerCe.SqlCeException(0x80004005): Указанная таблица не существует. [__MigrationHistory ]

- оператор # 10 начинает транзакцию с уровнем изоляции: Serializable

- оператор # 11 CREATE TABLE [Dummies] (      [DummyId] [int] NOT NULL IDENTITY,      [test] nvarchar,      [addThis] nvarchar,      CONSTRAINT [PK_Dummies] ПЕРВИЧНЫЙ КЛЮЧ ([DummyId]))

- оператор # 12 CREATE TABLE [__MigrationHistory] (      [MigrationId] nvarchar NOT NULL,      [CreatedOn] [datetime] NOT NULL,      [Модель] [изображение] NOT NULL,      [ProductVersion] nvarchar NOT NULL,      CONSTRAINT [PK___MigrationHistory] ПЕРВИЧНЫЙ КЛЮЧ ([MigrationId]))

- оператор # 13 INSERT INTO [__MigrationHistory]             ([MigrationId],              [Создано на],              [Модель],              [ProductVersion]) VALUES ('201208101940587_InitialCreate',              '2012-08-10T19: 40: 59,055', 0x1F8B0800000000000400CD57DD8ED33C10BDFF24DE21F23D75591082550A5ADA5D5441771159B89FC6D3D6C27642ECACDA67FB2E78245E8171FE9A26FDD95D40E2AE998CCF1C1F9FF1A43FFFFF11BE5D6B15DC6166656246ECD960C802347122A4598E58EE164F5FB1B76F9EFC175E0ABD0EBED679673E8F561A3B622BE7D273CE6DBC420D76A0659C253659B8419C680E22E167C3E12BFE6CC8912018610541F839374E6A2C1EE8719C98185397839A250295ADE2F4262A50836BD068538871C4DE8195F198D2AE64661D0B2E94046211A15A3C90D2F0B5A7C49A6254EE9268B9CDED26C5A2E4884D72AD37ED144AFA809B9D00853E65498A99DB7CC6457BE154B080EF2EE6DDD5CDDAEE42CF62C4A6C63D3F63C175AE14CC150516A02CB2207D791EB924C3F768300387E2133887199DCD5460B18B4A8DF3F4E5FD0479CD87675E100EC6240E1C1D748F7D87AB437F0225D1C865E419165CC9358A8F68966ED5909DC1BA8EBC180EC93A5F8C248F79842CC7F6EECAE7E3554188DB95B47FBB70C8B76EE87B842CEB4092F615A95911C1B5EB98A5CC8ED0B58E572291DF8297E61D9456DB4BA129B66D0C5E7646DD41FC400B8533485392A7D552552488CA7E1A3F8D1EDE37BAC4E0B1DDD33E0DDBA612191596D8794BA5EB2E9E808339F8031B0BDD4B3B2 96D5D6757E16E8F6E05AFF3FDEF72CDEEA532D8D3F56DE9AE68379A9AACD8183634F6DE16D5CA280605D9A1561F272AD7E6E8C5710CA76CC3364819B93F42D3526D9026D8C70979478AAED8BCA776E71AEC1EDE31D777539AEA8DFB3B2E0F2BC79D9E263D0B96292C2081EEA4F0F68B36D6A11EF88441F45D4598D1B81CE3E0859F8175DA0C8C5C90E8B7C937A43BB878F7D8C9D45CC4D60AF58F8F2769C8672707516F7ADD7FAC983BC8E215647BEEF2DF9A1A8FC47DD850E85F70A787C3E6F06828BD3962629ED0364A8ACD3C79E4DCE8774AC8DB5F67E104AD5C6E21FCB79AC1D87F1D6C41EB9CA95924B5ECB4AB36A33AA5732A337420489C8BCCC905C48E5EC7686D31D0BF82CA29E552CF514CCD4DEED2DC5D588B7AAE76E664C88FD72F86E32EE7F026F54FF64F6C81684ADA02DE9877B954A2E17DD5B7FA2108EF93AA7F88157DD010DC72D3205D27E69E40957C134CD1F8EEBB459D2A02B33726823B3CCCEDB486BB8A851309CB0C745BC132523189802AB74A5081F68A6D3DFFE782FB7F176F7E018E4F04B08F0C0000              , '4.3.1')

- оператор # 14 совершает транзакцию

- оператор # 15 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [Dummies] AS [Extent1]) AS [GroupBy1]

Что исправляет проблему, создав таблицу в нужном месте:

enter image description here

Как только я это сделал, в следующий раз, когда код запустится, все прошло отлично.

- оператор # 1 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- оператор # 2 SELECT TOP (1) [c]. [ProductVersion] AS [ProductVersion] FROM [__MigrationHistory] AS [c]

- оператор # 3 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- оператор # 4 SELECT [Extent1]. [MigrationId] AS [MigrationId] FROM [__MigrationHistory] AS [Extent1]

- оператор # 5 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- оператор # 6 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- оператор # 7 SELECT TOP (1) [Project1]. [C1] AS [C1],                [Project1]. [MigrationId] AS [MigrationId],                [Project1]. [Model] AS [Model] FROM (SELECT [Extent1]. [MigrationId] AS [MigrationId],                [Extent1]. [CreatedOn] AS [CreatedOn],                [Extent1]. [Модель] AS [Модель],                1 AS [C1]         FROM [__MigrationHistory] AS [Extent1]) AS [Project1] ORDER BY [Project1]. [CreatedOn] DESC

- оператор # 8 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]

- оператор # 9 SELECT TOP (1) [Project1]. [C1] AS [C1],                [Project1]. [MigrationId] AS [MigrationId],                [Project1]. [Model] AS [Model] FROM (SELECT [Extent1]. [MigrationId] AS [MigrationId],                [Extent1]. [CreatedOn] AS [CreatedOn],                [Extent1]. [Модель] AS [Модель],                1 AS [C1]         FROM [__MigrationHistory] AS [Extent1]) AS [Project1] ORDER BY [Project1]. [CreatedOn] DESC

- оператор # 10 начинает транзакцию с уровнем изоляции: Unspecified

- инструкция # 11 insert [Dummies]        ([контрольная работа],         [addThis]) значения (null,         нуль);

выберите [DummyId] из [Dummy], где [DummyId] = @@IDENTITY

- инструкция # 12 insert [Dummies]        ([контрольная работа],         [addThis]) значения (null,         нуль);

выберите [DummyId] из [Dummy], где [DummyId] = @@IDENTITY

- инструкция # 13 insert [Dummies]        ([контрольная работа],         [addThis]) значения (null,         нуль);

выберите [DummyId] из [Dummy], где [DummyId] = @@IDENTITY

- инструкция # 14 insert [Dummies]        ([контрольная работа],         [addThis]) значения (null,         нуль);

выберите [DummyId] из [Dummy], где [DummyId] = @@IDENTITY

- оператор # 15 совершить транзакцию

- оператор # 16 SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT COUNT (1) AS [A1]         FROM [Dummies] AS [Extent1]) AS [GroupBy1]

Если сбросить весь SDF и позволить ему воссоздать, это не вариант, вот что я сделал, чтобы вернуть его.

Создайте строку соединения в appconfig (я понимаю, что вы, вероятно, хотите динамические строки подключения, почему это в вашем коде, но это должно быть одно время). Строка подключения выглядела так:

   <connectionStrings>
        <add connectionString="Data Source=MyContext.sdf;Persist Security Info=False;" name="MyContext" providerName="System.Data.SqlServerCe.4.0"/>
    </connectionStrings>

Измените конструктор вашего Контекста так, чтобы он использовал строку подключения:

public MyContext()
    //: base(string.Format(@"DataSource=""{0}""", "MyContext.sdf"))
    : base("MyContext")

Все это необходимо, поэтому вы можете запускать некоторые команды в консоли диспетчера пакетов, чтобы он заново создавал таблицу. Откройте консоль диспетчера пакетов и выполните следующую команду:

add-migration initial -ignorechanges

Затем запустите программу - она ​​выведет некоторые предупреждения, но затем она создаст для вас таблицу и заполнит ее. После этого вы можете изменить свой конструктор, и у меня больше не было проблем.

Примечание: после того, как он начал работать, функция семян начала работать, а

Ответ 3

Я играл с кодом, который вы предоставили, и в этом случае (с SQL Server вместо CE) и пришел к следующему. Я удалил код Database.Create и разрешил автоматические миграции EF, чтобы сделать это. Это выполняется и вызывает метод Seed правильно.

internal class Program
{
    private static void Main()
    {
        EntityFrameworkProfiler.Initialize();

        Database.DefaultConnectionFactory = new SqlConnectionFactory("System.Data.SqlServer");
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, MyContextConfiguration>());

        using (var context = new MyContext())
        {
            var element = context.Dummies.FirstOrDefault();
        }
    }
}

internal class Dummy
{
    public String Id { get; set; }
}

internal sealed class MyContext : DbContext
{
    public MyContext() : base(@"Data Source=localhost;Initial Catalog=Dummies;User Id=<USER_ID>;Password=<PASSWORD>;MultipleActiveResultSets=False;")
    {
    }

    public DbSet<Dummy> Dummies { get; set; }
}

internal sealed class MyContextConfiguration : DbMigrationsConfiguration<MyContext>
{
    public MyContextConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }

    protected override void Seed(MyContext context)
    {
        context.Dummies.AddOrUpdate(new Dummy() { Id = "First" });
    }
}

Если вы посмотрите в профилировщике EF, вы увидите, что теперь есть больше запросов к базе данных (и даже проверка старой таблицы EdmMetaData... что очень странно, так как она должна упасть из этой таблицы, если она столкнулась теперь в пользу таблицы __MigrationHistory). Я не знаю, почему это происходит, я думаю, что это проблема конфигурации нашей стороны (которой я еще не знаю, как исправить), или это ошибка в коде миграции.

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