Adding Default Value for New Guid Column in Entity First Migration - asp.net-mvc

I am using Entity code first-migrations for my project. I already have the system up and running. However, I need to Add a new Guid column which is a foreign key. While trying to update-Database, I receive the following error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Categories_dbo.aspnet_Roles_RoleId". The conflict occurred in
database "HelpDesk", table "dbo.aspnet_Roles", column 'RoleId'.
So I did some research and found Entity Framework 6 Code first Default value. However, I cannot figure out how to get it to set a default value for the Guid. Here is the code I tried:
Here is the migration:
public override void Up()
{
AddColumn("dbo.Categories", "RoleId", c => c.Guid(nullable: false, defaultValue: "4468ACB7-AD6F-471E-95CF-615115EA3A76"));
CreateIndex("dbo.Categories", "RoleId");
AddForeignKey("dbo.Categories", "RoleId", "dbo.aspnet_Roles", "RoleId");
}
public override void Down()
{
DropForeignKey("dbo.Categories", "RoleId", "dbo.aspnet_Roles");
DropIndex("dbo.Categories", new[] { "RoleId" });
DropColumn("dbo.Categories", "RoleId");
}
I am able to get rid of all the build errors if I switch to this code (but still gives me that Alter Table error if I run Update-database:
AddColumn("dbo.Categories", "RoleId", c => c.Guid(nullable: false, identity: false, defaultValue: null));
How do I convert this to add a specific Guid as the default value?

I suppose you already figured it out, but I think (untested):
This should work for a constant (fixed) C#-Guid-value:
AddColumn("dbo.Categories", "RoleId", c => c.Guid(nullable: false, defaultValue: new Guid("4468ACB7-AD6F-471E-95CF-615115EA3A76")));
This should work for a constant (fixed) C#-string-value using defaultValueSql:
AddColumn("dbo.Categories", "RoleId", c => c.Guid(nullable: false, defaultValueSql: "4468ACB7-AD6F-471E-95CF-615115EA3A76")));
And for others (like me) looking for a varying, unique value (different per table row), determined by SqlServer, you may want to use defaultValueSql: "NewId()" (inspired by this answer):
AddColumn("dbo.Categories", "RoleId", c => c.Guid(nullable: false, defaultValueSql: "NewId()")));
Edit: untested, but probably also possible is a varying, unique, sequential value (different per table row), determined by SqlServer, by using defaultValueSql: "newsequentialid()" (inspired by this answer):
AddColumn("dbo.Categories", "RoleId", c => c.Guid(nullable: false, defaultValueSql: "newsequentialid()")));
But note that SqlServer increases/sorts the sequence different from C#. Which is why C# does also provides SqlGuid), so maybe this should be:
AddColumn("dbo.Categories", "RoleId", c => c.SqlGuid(nullable: false, defaultValueSql: "newsequentialid()")));
FWIW: sequential Guids often may make a better clustered index, but note the disadvantages:
they may be guessed
they are only locally sequential

Using the Entity Framework Migration Builder:
The defaultValue set the PK to a single new Guid on my first run. Using defaultValueSql: "NewId()" instead worked perfectly for my purposes.
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropUniqueConstraint("PK_Payments", "Payments");
migrationBuilder.DropColumn(
name: "PaymentId",
table: "Payments");
migrationBuilder.AddColumn<Guid>(
name: "PaymentId",
table: "Payments",
type: "uniqueidentifier",
defaultValueSql: "NewId()",
nullable: false);
}

From the error, I supposed you copied this Guid value "4468ACB7-AD6F-471E-95CF-615115EA3A76" from the database and wanted to use it for a test purpose and EF noticed the value already exist in a table and is complaining. It is also preventing you from using null, because you told it to prevent nulls,nullable: false. So it is expecting you to provide it with a value. You can create a new Guid and use it. See below
AddColumn("dbo.Categories", "RoleId", c => c.Guid(nullable: false, defaultValue: Guid.NewGuid().ToString()));

Could it be that your database initializer is using the default initializer (CreateDatabaseIfNotExists)? Alterations to those may sometimes lead to similar issues.
This may not be your final answer, but it could be related to the problem. I've attached a link to a decent article on database Initializers, it may help you isolate your problem.
http://www.codeguru.com/csharp/article.php/c19999/Understanding-Database-Initializers-in-Entity-Framework-Code-First.htm
From what I can tell, your code doesen't seem to be the immediate cause of the issue, it looks more like the migration script being generated that is causing problems.

Related

Invalid column name 'UserId' and 'IdentityUser_Id' when trying to log-in/register

I have been trying to build my own online shop in MVC based on the OpenOrderFramework located here - https://github.com/lbacaj/OpenOrderFramework
I've managed to get everything working perfectly apart from when it comes to trying to log in, register, or complete checkout - basically anything to do with Identity.
The error I keep getting is either:
Invalid column name 'UserId'.
or
Invalid column name 'IdentityUser_UserId'.
As part of the process, I have created my own custom AspNet Identity tables (AspNetRoles, AspNetUserClaims, AspNetUserLogins, AspNetUserRoles, AspNetUsers)
When I say custom, they all follow the standardised default format apart from the AspNetUsers table which has some additional new fields in there. They are nevertheless fed into the project like so:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder); // This needs to go before the other rules!
modelBuilder.Entity<ApplicationUser>().ToTable("TSSC_AspNetUsers", "dbo");
modelBuilder.Entity<IdentityUser>().ToTable("TSSC_AspNetUsers", "dbo");
modelBuilder.Entity<IdentityUserRole>().ToTable("TSSC_AspNetUserRoles", "dbo");
modelBuilder.Entity<IdentityRole>().ToTable("TSSC_AspNetRoles", "dbo");
modelBuilder.Entity<IdentityUserLogin>().ToTable("TSSC_AspNetUserLogins", "dbo");
modelBuilder.Entity<IdentityUserClaim>().ToTable("TSSC_AspNetUserClaims", "dbo");
}
Depending on what I try, the invalid column name error can appear up to three times for the same field which I find odd.
I took a look at the SQL query string being generated inside the UserManager and this is what it returned:
+
((Microsoft.AspNet.Identity.UserManager<TSSC.Models.ApplicationUser,string>)(UserManager)).Users {SELECT
'0X0X' AS [C1],
[Extent1].[IdentityUser_Id] AS [IdentityUser_Id],
[Extent1].[Email] AS [Email],
[Extent1].[EmailConfirmed] AS [EmailConfirmed],
[Extent1].[PasswordHash] AS [PasswordHash],
[Extent1].[SecurityStamp] AS [SecurityStamp],
[Extent1].[PhoneNumber] AS [PhoneNumber],
[Extent1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Extent1].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Extent1].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Extent1].[LockoutEnabled] AS [LockoutEnabled],
[Extent1].[AccessFailedCount] AS [AccessFailedCount],
[Extent1].[UserName] AS [UserName]
FROM [dbo].[TSSC_AspNetUsers] AS [Extent1]
WHERE [Extent1].[Discriminator] = N'ApplicationUser'}
System.Linq.IQueryable<TSSC.Models.ApplicationUser>
{System.Data.Entity.DbSet<TSSC.Models.ApplicationUser>}
As you can see, it is looking for a column called 'IdentityUser_UserId' which doesn't exist. The field is actually 'Id'.
Any help or advice would be appreciated. This is driving me nuts.

How do I specify the name of a joiner table in an EF many to many relationship?

I am using EF Code First 6.2 With Dev Express XAF
In DevExpress.Persistent.BaseImpl.EF the Event class has a many to many relationship with the Resource class.
If I make a new project using the Dev Express Wizard with Code First then the joiner table will be called ResourceEvents
However somehow in some migration my joiner table got renamed to be EventResources.
How do I set it back to what it should be?
I tried adding the following to the DBContext
modelBuilder.Entity<Event>().HasMany(x => x.Resources).WithMany(x => x.Events)
.Map(
x =>
{
x.MapLeftKey("Event_ID");
x.MapRightKey("Resource_Key");
x.ToTable("ResourceEvents");
});
this causes a migration to want to create
public partial class ev : DbMigration
{
public override void Up()
{
DropPrimaryKey("dbo.ResourceEvents");
AddPrimaryKey("dbo.ResourceEvents", new[] { "Event_ID", "Resource_Key" });
}
public override void Down()
{
DropPrimaryKey("dbo.ResourceEvents");
AddPrimaryKey("dbo.ResourceEvents", new[] { "Resource_Key", "Event_ID" });
}
}
Running the migration causes an error
Cannot find the object "dbo.ResourceEvents" because it does not exist or you do not have permissions.
The trick was to add code to the migration to rename the table
RenameTable(name: "dbo.EventResources", newName: "ResourceEvents");
Having the fluent API seems important in letting EF know what the name of the table should be.

Code First migration from int to Guid primary key issue

I'm trying to change my code first ID column from 'int' to 'Guid', and when trying to run the migration, I get the message:
Identity column 'CustomFieldId' must be of data type int, bigint, smallint, tinyint, or decimal or numeric with a scale of 0, and constrained to be nonnullable.
I'm defining the column like this:
public partial class CustomField : BaseEntity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid CustomFieldId { get; set; }
Mapping it in CustomFieldMapping.cs like this:
public CustomFieldMapping()
{
//Primary key
HasKey(t => t.CustomFieldId);
//Constraints
Property(t => t.CustomFieldId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
And the migration that's generated is trying to do this:
public override void Up()
{
DropForeignKey("dbo.CustomField", "CustomFormId", "dbo.CustomForm");
DropForeignKey("dbo.CustomData", "CustomFieldId", "dbo.CustomField");
DropForeignKey("dbo.CustomForm", "ParentFormId", "dbo.CustomForm");
DropIndex("dbo.CustomField", new[] { "CustomFormId" });
DropIndex("dbo.CustomForm", new[] { "ParentFormId" });
DropIndex("dbo.CustomData", new[] { "CustomFieldId" });
DropPrimaryKey("dbo.CustomField");
DropPrimaryKey("dbo.CustomForm");
AlterColumn("dbo.CustomField", "CustomFieldId", c => c.Guid(nullable: false));
AlterColumn("dbo.CustomField", "SortOrder", c => c.Int(nullable: false));
AlterColumn("dbo.CustomForm", "CustomFormId", c => c.Guid(nullable: false));
AlterColumn("dbo.CustomForm", "ParentFormId", c => c.Guid());
AddPrimaryKey("dbo.CustomField", "CustomFieldId");
AddPrimaryKey("dbo.CustomForm", "CustomFormId");
CreateIndex("dbo.CustomField", "CustomForm_CustomFormId");
CreateIndex("dbo.CustomForm", "ParentFormId");
CreateIndex("dbo.CustomData", "CustomField_CustomFieldId");
AddForeignKey("dbo.CustomField", "CustomForm_CustomFormId", "dbo.CustomForm", "CustomFormId");
AddForeignKey("dbo.CustomData", "CustomField_CustomFieldId", "dbo.CustomField", "CustomFieldId");
AddForeignKey("dbo.CustomForm", "ParentFormId", "dbo.CustomForm", "CustomFormId");
I would like it to be a sequentially incremented Guid. What am I doing wrong?
To solve this problem I used a Sql() method in the Up() and Down() methods of the migration class. The SQL command string in the Up() method removes the primary key constraint on the ID column, drops the ID column of type int and then adds a new ID column with of type Guid. The Down() method does the same thing but drops the Guid column and adds a new int column.
I found a few solutions on Stack Overflow that resolve the "change column type" by running a SQL command in a query window. To address your comment:
We're just trying to keep a clean/clear migration path to trace when
we did what which is not always easy with SQL.
I used SQL commands within the Up() and Down() migration methods. For me this solution works well in my projects.
The solution at the bottom of this answer was constructed from several Stack Overflow questions/answers. Skip to that for just the code. Here are the long-winded details.
Using SQL commands in a migration class
I couldn't find a solution that used Entity Framework migration methods like AlterColumn() and DropColumn() ONLY.
Rather than using a mix of migration methods and commands in the Sql() method, I used all SQL commands within a string in the Sql() migration method. Using all SQL commands made it easier to test in a query window in Visual Studio or SQL Server Management Studio.
The answer by 'Uchitha' gave the starting steps for adding the Sql() "method within the desired migration class."
Generate migration class using Add-Migration
Alter the class using code similar to above
Run the migration using Update-Database
The Sql() method sample in the answer looks like:
Sql("UPDATE dbo.YourTable SET Column1 = 'VALUE1' ");
Changing the column type - generic steps
I used the answer by 'JustAnotherUserYouMayKnow' to get started on the steps to change the column type. I didn't follow this explicitly but it provided just the basic framework of the need to drop a column and recreating it.
Add a new column with your new type
Use Sql() to take over the data from the original column using an update statement
Remove the old column
Rename the new column
Sequential GUIDs
The answer from 'Icarus' provided the ALTER TABLE statement with the use of newsequentialid() to generate sequential GUIDs as per your statement:
I would like it to be a sequentially incremented Guid.
ALTER TABLE your_table
ADD your_column UNIQUEIDENTIFIER DEFAULT newsequentialid() NOT null
Take note of privacy concerns by 'Johan' in the comment section of the answer by 'Icarus':
If privacy is a concern, do not use newsequentialid(). It is possible to guess the value of the next generated GUID and, therefore, access data associated with that GUID
Alter primary key
The column you want to change is an ID column and you've set it as the primary key. Therefore, before dropping the existing ID column you'll need to remove the primary key using another ALTER TABLE SQL command.
See the selected answer from 'darnir' for "How can I alter a primary key constraint using SQL syntax?"
ALTER TABLE <Table_Name>
DROP CONSTRAINT <constraint_name>
ALTER TABLE <Table_Name>
ADD CONSTRAINT <constraint_name> PRIMARY KEY (<Column1>,<Column2>)
See the note by 'Oleg' to determine if this will be a factor:
PRIMARY KEY CONSTRAINT cannot be altered, you may only drop it and create again. For big datasets it can cause a long run time and thus - table inavailability.
I had problems when the command with DROP CONSTRAINT above was executed. The results pane listed a constraint that was auto-generated even though I'd used a specific constraint name in the ALTER TABLE ... ADD COLUMN command. See this question "Why does SQL keep creating a DF constraint?" and this question if you experience something similar.
To fix the problem with dropping the constraint I used the answer by 'ScubaSteve' from this question: "How to drop SQL default constraint without knowing its name?" With the addition of the note by 'Seven' here are the SQL commands:
DECLARE #ObjectName NVARCHAR(100)
SELECT #ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID('[tableSchema].[tableName]') AND [name] = 'columnName';
IF #ObjectName IS NOT NULL EXEC('ALTER TABLE [tableSchema].[tableName] DROP CONSTRAINT ' + #ObjectName)
The comment by 'Seven' in 'ScubaSteve's answer. I added the 'if' condition as at times the EXEC would fail when no constraint was found.
To make this script idempotent add IF #ObjectName IS NOT NULL before EXEC command
The final solution
Make sure to replace MyTableName, MyColumnName, and dbo in the code below to your table name, column name (e.g. set column name to Id) and table schema respectively.
public override void Up()
{
Sql(#"
DECLARE #ObjectName NVARCHAR(100)
SELECT #ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID('[dbo].[MyTableName]') AND [name] = 'MyColumnName';
IF #ObjectName IS NOT NULL EXEC('ALTER TABLE [dbo].[MyTableName] DROP CONSTRAINT ' + #ObjectName)
ALTER TABLE dbo.MyTableName DROP CONSTRAINT PK_MyTableName, COLUMN MyColumnName
ALTER TABLE dbo.MyTableName
ADD Id UNIQUEIDENTIFIER DEFAULT (newsequentialid()) NOT NULL
CONSTRAINT PK_MyTableName
PRIMARY KEY CLUSTERED ([MyColumnName])
");
}
public override void Down()
{
Sql(#"
DECLARE #ObjectName NVARCHAR(100)
SELECT #ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID('[dbo].[MyTableName]') AND [name] = 'MyColumnName';
IF #ObjectName IS NOT NULL EXEC('ALTER TABLE [dbo].[MyTableName] DROP CONSTRAINT ' + #ObjectName)
ALTER TABLE dbo.MyTableName DROP CONSTRAINT PK_MyTableName, COLUMN Id
ALTER TABLE MyTableName
ADD MyColumnName int IDENTITY(1, 1) NOT NULL
CONSTRAINT PK_MyTableName
PRIMARY KEY CLUSTERED ([MyColumnName] ASC)
");
}
I found a simple solution for the problem. You just need to drop the column CustomFieldId then add it back as a Guid column. That way there won't be any error message and the migration will pass:
public override void Up()
{
DropForeignKey("dbo.CustomField", "CustomFormId", "dbo.CustomForm");
DropForeignKey("dbo.CustomData", "CustomFieldId", "dbo.CustomField");
DropForeignKey("dbo.CustomForm", "ParentFormId", "dbo.CustomForm");
DropIndex("dbo.CustomField", new[] { "CustomFormId" });
DropIndex("dbo.CustomForm", new[] { "ParentFormId" });
DropIndex("dbo.CustomData", new[] { "CustomFieldId" });
DropPrimaryKey("dbo.CustomField");
DropPrimaryKey("dbo.CustomForm");
DropColumn("dbo.CustomField", "CustomFieldId")
AddColumn("dbo.CustomField", "CustomFieldId", c => c.Guid(nullable: false));
AlterColumn("dbo.CustomField", "SortOrder", c => c.Int(nullable: false));
AlterColumn("dbo.CustomForm", "CustomFormId", c => c.Guid(nullable: false));
AlterColumn("dbo.CustomForm", "ParentFormId", c => c.Guid());
AddPrimaryKey("dbo.CustomField", "CustomFieldId");
AddPrimaryKey("dbo.CustomForm", "CustomFormId");
CreateIndex("dbo.CustomField", "CustomForm_CustomFormId");
CreateIndex("dbo.CustomForm", "ParentFormId");
CreateIndex("dbo.CustomData", "CustomField_CustomFieldId");
AddForeignKey("dbo.CustomField", "CustomForm_CustomFormId", "dbo.CustomForm", "CustomFormId");
AddForeignKey("dbo.CustomData", "CustomField_CustomFieldId", "dbo.CustomField", "CustomFieldId");
AddForeignKey("dbo.CustomForm", "ParentFormId", "dbo.CustomForm", "CustomFormId");

Adding to EntitySet not working

I'm trying to add an object to a database-first ORM EntitySet in an MVC project. I use a piece of code something like this:
public static Boolean CreateListing(string title, string description)
{
ListingEntities ce = new ListingEntities();
ce.Ads.AddObject(new Ad()
{
ID = Guid.NewGuid(),
Title = title,
Description = description,
});
return ce.SaveChanges() == 1;
}
However, the SaveChanges method throws a Data.UpdateException which is thrown by a SqlClient.SqlException. The latter says
"Cannot insert the value NULL into column 'ID', table 'Listings.dbo.Ads'; column does not allow nulls. INSERT fails.
The statement has been terminated."
I wholeheartedly agree. I just don't see why the ID should be null when it seems I set it immediately prior. Any suggestions?
Thanks,
Nathan
Someone else on my team configured the database to create its own ID's, and the issue is resolved.

Entity Framework 4.3.1 Code First: database created but tables are not

Today I migrated an old application from EF 4.2 to EF 4.3.1.
In my app I was using CodeFirst, but after migration it stopped working, and couldn't find a reason for that.
To clear any other possible problem I decided to create a small console application and I used the Data Migration walk-through published by the ADO team:
http://blogs.msdn.com/b/adonet/archive/2012/02/09/ef-4-3-code-based-migrations-walkthrough.aspx
I copied exactly the code of the blog, but instead of working correctly (creating the DB, creating the schema, and inserting the blog) I get some errors:
only the DB is created, but no tables
I get this error Conversion failed when converting datetime from character string."
All of this is on SQL Server 2005 express.
I tried the same using SQL Compact, but same result (tho different error):
only the DB is created (in this case a sdf file in the bin folder), but no tables
I get the error The format of the specified date or time datepart is not valid. [ String = 2012-04-19T13.21.04.364 ]
I think in both cases the problem lies in the line that EF wants to enter as first migration:
INSERT INTO [__MigrationHistory] ([MigrationId], [CreatedOn], [Model], [ProductVersion])
VALUES ('201204191321184_init', '2012-04-19T13.21.04.364', ...., '4.3.1');
Apparently the format with the . is wrong, at least in my locale, it should be with :
Is this a bug or what? It always worked with other datetime before.
UPDATE
I tried running it as explicit migration, and applying the migration with the -verbose flag set, and here is what I get:
PM> Update-Database -Verbose
Using NuGet project 'ConsoleApplication2'.
Using StartUp project 'ConsoleApplication2'.
Target database is: '|DataDirectory|ConsoleApplication2.ConsoleApplication1.BlogContext.sdf' (DataSource: |DataDirectory|ConsoleApplication2.ConsoleApplication1.BlogContext.sdf, Provider: System.Data.SqlServerCe.4.0, Origin: Convention).
Applying explicit migrations: [201204191356197_Initial].
Applying explicit migration: 201204191356197_Initial.
CREATE TABLE [Blogs] (
[BlogId] [int] NOT NULL IDENTITY,
[Name] [nvarchar](4000),
CONSTRAINT [PK_Blogs] PRIMARY KEY ([BlogId])
)
CREATE TABLE [__MigrationHistory] (
[MigrationId] [nvarchar](255) NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[Model] [image] NOT NULL,
[ProductVersion] [nvarchar](32) NOT NULL,
CONSTRAINT [PK___MigrationHistory] PRIMARY KEY ([MigrationId])
)
[Inserting migration history record]
System.Data.SqlServerCe.SqlCeException (0x80004005): The format of the specified date or time datepart is not valid. [ String = 2012-04-19T13.56.45.437 ]
at System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 hr)
at System.Data.SqlServerCe.SqlCeCommand.ExecuteCommandText(IntPtr& pCursor, Boolean& isBaseTableCursor)
at System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(CommandBehavior behavior, String method, ResultSetOptions options)
at System.Data.SqlServerCe.SqlCeCommand.ExecuteNonQuery()
at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements)
at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, Boolean downgrading)
at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()
at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
The format of the specified date or time datepart is not valid. [ String = 2012-04-19T13.56.45.437 ]
Update 2
I installed SQL Server Profiler, and profiled what is happening over there.
I executed all the statements one by one via query analyzer and the one that fails is, as already stated above, the insertion of the migration.
INSERT INTO [__MigrationHistory] ([MigrationId], [CreatedOn], [Model], [ProductVersion]) VALUES ('201204231416585_InitialCreate', '2012-04-23T14.16.59.038Z', ...., '4.3.1')
When changing the format of the datatime string from 2012-04-23T14.16.59.038Z to 2012-04-23T14:16:59.038Z the command went through, so I guess somehow EF is sending the datatime in format that is not compatible with my locale.
Thank you
Simone
Thanks to the ADO.NET Team, this was a bug in the Migration code.
Apparently they forgot to specify InvariantCulture when they generate code for a DateTime field, so it works on EN locale, but doesn't in other locales.
To fix this problem, waiting for an official fix, you should specify a custom SqlGenerator that overrides the Generate(DateTime defaultValue) method:
class FixedSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override string Generate(DateTime defaultValue)
{
return "'" + defaultValue.ToString("yyyy-MM-ddTHH:mm:ss.fffK", CultureInfo.InvariantCulture) + "'";
}
}
And then specify the new SqlGenerator in the Configuration class:
SetSqlGenerator("System.Data.SqlClient", new FixedSqlGenerator());
If you want to use it just in manual migrations that's enough, if you only need CodeFirst, you have to specify the configuration in the application startup code or in the DbContext.
Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogContext, Migrations.Configuration>());
HTH
I had the same problem with a brand new project, in my case I solved it by specifying the right culture in my web.config
<globalization enableClientBasedCulture="false" culture="en-US" />

Resources