ASP.NET MVC 3, EF, SQL Server: попытка обновления базы данных, вызывающая необъяснимую ошибку - PullRequest
0 голосов
/ 03 марта 2012

Я использую базу данных, которая была сгенерирована Entity Framework с использованием модели Code First.С тех пор я несколько раз менял модель и знакомился с Консоль диспетчера пакетов, которая генерирует код для изменения базы данных в соответствии с изменениями в вашей модели.

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

public int Rowversion { get; set; }
public DateTime MLTimestamp { get; set; }

Второе поле называется «MLTimestamp», но изначально оно называлось Timestamp.Я изменил его, пытаясь исправить ошибку, полученную при обновлении базы данных.

Итак, вот код, сгенерированный менеджером пакетов:

public partial class MediaTypeRowversion : DbMigration
{
    public override void Up()
    {
        AddColumn("MediaTypes", "Rowversion", c => c.Int(nullable: false));
        AddColumn("MediaTypes", "MLTimestamp", c => c.DateTime(nullable: false));
    }

    public override void Down()
    {
        DropColumn("MediaTypes", "MLTimestamp");
        DropColumn("MediaTypes", "Rowversion");
    }
}

Когда я запустил Update-Databaseиз консоли диспетчера пакетов я получил это сообщение об ошибке:

The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
The statement has been terminated.

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

Ни одно из этих полей не помечено данными как Timestamp.Учитывая, как разочаровывает EF в работе, я подумал, что было бы проще реализовать мою собственную проверку параллелизма строк, и это работало как прелесть в макете Session-State.

Я попытался просто удалить свой .mdfи добавление еще одного файла с таким же именем, чтобы, возможно, он снова создавал таблицы с нуля, но, о, нет, это, очевидно, решить не так просто.Я открыт для идеи просто хранить метку времени в виде строки, так как EF, кажется, получает несварение при попытке перехода между значениями DateType в C # и значениями даты и времени в SQL Server, но я бы предпочел сохранить это какDateTime, если это возможно.

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

Ответы [ 2 ]

2 голосов
/ 03 марта 2012

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

Попробуйте сделать метку времени DateTime? то есть обнуляемый. В качестве альтернативы, я считаю, что Migrations предоставляет вам способ предоставить значение по умолчанию для использования для существующих столбцов (не на моем ПК, поэтому не могу проверить).

0 голосов
/ 15 августа 2012

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

Это приведет к тому, что столбец, не имеющий значения NULL, не будет иметь определения значения по умолчанию (то есть вы должны указывать его каждый раз, когда выполняете любую вставку - sql никогда не будет генерировать дату и время).

public partial class AddDateColumToMyEntity : DbMigration
{
    public override void Up()
    {
        // EF4.3 bug, gotta create date nullable, then change to non-nullable
        AddColumn("MyEntity", "SomeDateField", c => c.DateTime(nullable: true));
        AlterColumn("MyEntity", "SomeDateField", c => c.DateTime(nullable: false));
    }
}
...