首先使用实体​​框架数据库强制DateTime

时间:2015-09-24 14:47:32

标签: sql-server entity-framework datetime ef-database-first datetime2

我首先使用EF数据库连接到数据库。因此我的模型是自动生成的。

当我更新记录时,我的DateTimes被写为SQL类型DateTime2。生产服务器是SQL Server 2005(请不要评论),因此更新失败,因为不支持DateTime2。

我已经尝试按照http://www.asp.net/mvc/overview/getting-started/database-first-development/enhancing-data-validation为我的模型创建元数据类,并使用[Column(DbType =“datetime”)]装饰成员,但要么我没有正确地遵循说明,要么我''我走错了路。

如何在写入数据库时​​首先使用EF数据库来使用DateTime?

由于

3 个答案:

答案 0 :(得分:3)

我以前遇到过这个问题,因为DateTime的实体框架标准是DateTime2字段,显然解决方法是将所有列更新到SQL Server数据库中的datetime2,但是datetime2数据类型仅在SQL Server 2008中引入,所以这里有一些尝试:

首先:确保如果SQL数据库中的DateTime字段可以为空,您的模型是否正在使用“DateTime?” (可以为空的日期时间)而不是“日期时间”。

第二:使用任何XML编辑器打开您的EDMX文件(Visual Studio应该工作)并将ProviderManifestToken的值更改为ProviderManifestToken="2005",这应该确保SQL Server 2005的兼容性。

适用于.edmx文件,但Code First更改将更具挑战性,并且将取决于您的实体框架版本,因此Microsoft建议您尝试在OnModelCreating方法上指定列类型,如下例所示:

modelBuilder.Entity<Blog>().Property(t => t.CreatedOn).HasColumnName("CreatedOn").HasColumnType("date");

尝试使用ColumnType的值,直到达到目标为止。

如果您仍想更改ProviderManifestToken值:

E.F。 6:你可以为你的DbContext创建一个配置,基本上是这样的一个类:

/// <summary>
/// A configuration class for SQL Server that specifies SQL 2005 compatability.
/// </summary>
internal sealed class EntityFrameworkDbConfiguration : DbConfiguration
{
    /// <summary>
    /// The provider manifest token to use for SQL Server.
    /// </summary>
    private const string SqlServerManifestToken = @"2005";

    /// <summary>
    /// Initializes a new instance of the <see cref="EntityFrameworkDbConfiguration"/> class.
    /// </summary>
    public EntityFrameworkDbConfiguration()
    {
        this.AddDependencyResolver(new SingletonDependencyResolver<IManifestTokenResolver>(new ManifestTokenService()));
    }

    /// <inheritdoc />
    private sealed class ManifestTokenService : IManifestTokenResolver
    {
        /// <summary>
        /// The default token resolver.
        /// </summary>
        private static readonly IManifestTokenResolver DefaultManifestTokenResolver = new DefaultManifestTokenResolver();

        /// <inheritdoc />
        public string ResolveManifestToken(DbConnection connection)
        {
            if (connection is SqlConnection)
            {
                return SqlServerManifestToken;
            }

            return DefaultManifestTokenResolver.ResolveManifestToken(connection);
        }
    }
}

用法:

DbConfigurationType(typeof(EntityFrameworkDbConfiguration))]
public class MyContextContext : DbContext
{
}

(来源:How to configure ProviderManifestToken for EF Code First

E.F。 5岁及以上:阅读这篇文章,轻松澄清:http://blog.oneunicorn.com/2012/04/21/code-first-building-blocks/

希望有所帮助。

答案 1 :(得分:2)

令人讨厌的是,费利普的建议没有用,虽然我看不出有什么理由不这样做。

我设法破解了我自己的解决方案。并不完全满意,但我们正试图让客户端升级到SQL Server 2014,因此它不是永久性的。欢迎评论......

首先我创建了这个类:

internal sealed class MyCommandInterceptor : IDbCommandInterceptor
{
    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }

    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        ChangeDateTime2ToDateTimeForSqlServer2005Compatibility(command);
    }

    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
    }

    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        ChangeDateTime2ToDateTimeForSqlServer2005Compatibility(command);
    }

    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
    }

    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
        ChangeDateTime2ToDateTimeForSqlServer2005Compatibility(command);
    }

    /// <summary>
    /// Changes parameters of type datetime2 to datetime for SQL server2005 compatibility.
    /// </summary>
    /// <param name="command">The command.</param>
    private void ChangeDateTime2ToDateTimeForSqlServer2005Compatibility(DbCommand command)
    {
        foreach (DbParameter param in command.Parameters)
        {
            if (param.DbType == System.Data.DbType.DateTime2)
            {
                param.DbType = System.Data.DbType.DateTime;
            }
        }
    }
}

然后我在DbContext派生类中使用静态构造函数激活它:

    static MyDbContext()
    {
        // The command interceptor changes DateTime2 data types to DateTime for SQL Server 2005 compatibility.
        DbInterception.Add(new MyCommandInterceptor());
    }

我会密切注意这一点,以确保它的行为。

答案 2 :(得分:0)

我通过删除数据库并在包管理器控制台中再次运行update-database命令来解决它。但不适合生产环境。