Frage

I'm using a database that was generated by Entity Framework using the Code First model. I've since changed the model a few times, and become acquainted with the Package Manager Console, which generates code to modify the database in accordance with changes to your model.

It's worked well so far, until I added a couple of fields to perform an optimistic concurrency control. These are the fields I added to my model:

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

The second field is named "MLTimestamp" but was originally named Timestamp. I changed it in an attempt to fix the error I received when trying to update the database.

So, here's the code the Package Manager produced:

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");
    }
}

When I ran Update-Database from the Package Manager console, I got this error message:

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

I'm not sure what conversion it thinks I'm trying to make. This was a field that did not exist in the database before. There's nothing to "convert." As mentioned above, the second field was originally named Timestamp, so I slapped my forehead and said, ah, there must already be a field with that name in the database. So I changed it in my model and in the migration code, but still, I get this error.

Neither of these fields are data-annotated as Timestamp. Given how frustrating EF already is to work with I figured it would be easier to just implement my own rowversion concurrency checking, and it worked like a charm on the Session-State mockup.

I tried simply deleting my .mdf file and and adding another one with the same name so that maybe it would build the tables again from scratch, but oh no, this is obviously not to be solved quite so simply. I'm open to the idea of just storing the timestamp as a string, since EF seems to get indigestion when trying to go back and forth between C# DateType values and SQL Server datetime values, but I'd rather try to keep this as a DateTime if possible.

Anyway, if anyone could offer some pointers on how I could move past this, I would be very grateful!

War es hilfreich?

Lösung

The time stamp field is not nullable. When SQL adds the column it doesn't have a default value for it. I am guessing that either SQL or EF tries to just supply an empty string for the new column on existing records and that causes the conversion problem.

Try making the timestamp DateTime? ie nullable. Alternatively, I believe Migrations provides you a way to supply a default value to use for existing columns (not at my PC so can't check).

Andere Tipps

@Frans has got you on the right track. However, if you want to accomplish this goal without changing your data model, you can modify your migration to add the DateTime column as nullable then alter it to be nullable.

This will result in a non-nullable column with no default value definition (meaning you must supply it everytime you do any insert - sql will never generate the datetime).

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));
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top