.net 将实体的DateTime列转换为字符串类型时指定格式
我有一个EF6 code first数据模型,它有一个包含日期属性的表Foo,如下所示:.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"
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));
}