.net 将实体的DateTime列转换为字符串类型时指定格式

.net 将实体的DateTime列转换为字符串类型时指定格式,.net,entity-framework,ef-code-first,entity-framework-6,entity-framework-migrations,.net,Entity Framework,Ef Code First,Entity Framework 6,Entity Framework Migrations,我有一个EF6 code first数据模型,它有一个包含日期属性的表Foo,如下所示: public class Foo { public DateTime Date { get; set; } } 我已将Date属性的类型更改为string,并创建了一个新的迁移,如下所示: public partial class v2 : DbMigration { public override void Up() { AlterColumn("dbo.Foo"

我有一个EF6 code first数据模型,它有一个包含日期属性的表Foo,如下所示:

public class Foo
{
    public DateTime Date { get; set; }
}
我已将Date属性的类型更改为string,并创建了一个新的迁移,如下所示:

public partial class v2 : DbMigration
{
    public override void Up()
    {
        AlterColumn("dbo.Foo", "Date", c => c.String());
    }

    public override void Down()
    {
        AlterColumn("dbo.Foo", "Date", c => c.DateTime());
    }
}
}

这是可行的,但是DateTimes被转换成了我能告诉我们的字符串表示形式,比如2015年11月23日下午5:39


有没有办法告诉EF为此使用不同的语言环境,或者以某种方式为其提供要使用的格式字符串?

当将SQL Server用作后端时,EF仅为SQL Server创建以下指令:

ALTER TABLE dbo.Foo ALTER COLUMN Date NVARCHAR(max)
SQL server将原始日期转换为字符串。而且没有办法改变格式。它既不考虑连接语言,也不考虑列排序规则。因此,我认为SQL Server根本无法被指示更改格式

不幸的是,没有办法指导SQLServer如何操作,您需要手动操作

然而,这个小SQL代码片段展示了如何使用T-SQL来实现这一点:

-为此演示创建一个表 创建表Foo Id INT标识主键, 日期时间 -添加一些示例数据 插入Foo日期值“2015-11-24T10:20:30.40” 插入Foo日期值“2015-11-26T11:22:33.44” 插入Foo日期值“2015-11-28512:24:36.48” -这显示了如何使用T-SQL -在alter列之前添加此项,以存储原始值 ALTER TABLE Foo ADD temp DATETIME 更新Foo SET temp=Date -EF迁移就是这样做的: ALTER TABLE Foo ALTER COLUMN Date NVARCHAR100 -执行此操作以更新更改的列值 更新Foo SET Date=FORMATtemp,'dd/mm/yyyy' -这将删除temp列 ALTER TABLE Foo DROP列温度 -看到结果了吗 从Foo中选择* -放下演示桌 放下桌子 因此,您需要通过在AlterColumn前后添加一些SQL执行来修改Up方法:

SqlALTER表格Foo ADD temp DATETIME; SqlUPDATE Foo SET temp=日期; AlterColumndbo.Foo,Date,c=>c.String; SqlUPDATE Foo SET Date=FORMATtemp,'dd/mm/yyyyy'; SqlALTER TABLE Foo DROP列温度; 注意:我使用FORMAT函数。根据您的SQL Server版本,您可能需要使用其他功能

注意:如果有可能进行向下迁移,请修改向下方法:将字符串转换为SQL Server理解的格式,更改列

由于需要对许多实例重复此操作,因此可以创建一个helper方法来执行pre和post SQL。EF迁移无法自动执行此操作。代码生成的ALTER列sql为:

如果您有很多实例,可以从codeplex加载代码,并修改此方法以包括前SQL和后SQL。alterColumnOperation参数包含有关表、列、类型等的足够信息。您可以执行以下操作:

            if (alterColumnOperation.Column.ClrType == typeof(DateTime)
                && alterColumnOperation.Column.ClrType == typeof(string))
            {
                writer.Write("ALTER TABLE ");
                writer.Write(Name(alterColumnOperation.Table));
                writer.Write(" ADD ");
                writer.Write(Quote("TMP__" + column.Name));
                writer.Write(BuildColumnType(column));
                writer.WriteLine();
                writer.Write("UPDATE ");
                writer.Write(Name(alterColumnOperation.Table));
                writer.Write(" SET ");
                writer.Write(Quote("TMP__" + column.Name));
                writer.Write(string.Format(" = FORMAT({0},'dd/mm/yyyy')"),
                    Quote("TMP__" + column.Name));
            }

为什么不手动调整字符串呢?只需先添加一个额外的列DateString。然后var temp=db.Foo.ToList;temp f.DateString=String.FormatCultureInfo中的Foreachvar f,{0:*formatstring*,f.Date;我考虑过作为最后的手段,但当您有许多列需要更改其类型时,这将是一项非常艰巨的工作。如果您可以为EF提供区域设置或格式字符串,则会方便得多。这甚至不需要编译。ColumnBuilder.string不接受字符串格式参数。
            if (alterColumnOperation.Column.ClrType == typeof(DateTime)
                && alterColumnOperation.Column.ClrType == typeof(string))
            {
                writer.Write("ALTER TABLE ");
                writer.Write(Name(alterColumnOperation.Table));
                writer.Write(" ADD ");
                writer.Write(Quote("TMP__" + column.Name));
                writer.Write(BuildColumnType(column));
                writer.WriteLine();
                writer.Write("UPDATE ");
                writer.Write(Name(alterColumnOperation.Table));
                writer.Write(" SET ");
                writer.Write(Quote("TMP__" + column.Name));
                writer.Write(string.Format(" = FORMAT({0},'dd/mm/yyyy')"),
                    Quote("TMP__" + column.Name));
            }