实体框架插入日期列失败



我有一个问题与实体框架(v6.1.0),如果一个DateTime属性被注释为日期类型:

Column(TypeName = "Date")

public class MyTable
{
    [DatabaseGenerated]
    public Guid Id { get; set; }
    [Key, Column(TypeName = "Date"), DataType(DataType.Date)]
    public DateTime DateKey { get; set; }
    [Required]
    public string SomeProperty { get; set; }
}

SQL中我的表的列被正确地创建为DATE列。

现在,如果我尝试插入一个新的行,并设置我的日期属性,例如与DateTime.Now(),我得到以下错误:

存储更新、插入或删除语句受意外影响行数(0)。实体可能被修改或删除实体被加载。刷新ObjectStateManager表项。

问题出在EF生成的SQL代码中:
exec sp_executesql N'
INSERT [dbo].[MyTable]([DateKey], [SomeProperty]) VALUES (@0, @1)
    SELECT [Id] FROM [dbo].[MyTable]
    WHERE @@ROWCOUNT > 0 AND [DateKey] = @0',
        N'@0 datetime2(7), @1varchar(max)',
        @0='2014-03-26 08:58:07', 
        @1='abcdef'

DateKey的参数声明为DATETIME2。我想,这应该是约会。如果有任何时间部分,这个select语句不能返回任何行。如果我将参数@0更改为DATE(正如我的模型中注释的那样),即使仍然包括时间部分,我也不会得到错误。

这是EF中的一个bug吗?

问候,丹尼尔

编辑:我不知道这是否与我的问题有关。默认情况下,我在OnModelCreating中配置了所有日期列为DATETIME2:

modelBuilder.Properties()。Configure(p => p. hascolumntype ("datetime2"));

编辑于2014-03-27提供完整的副本:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    namespace EFDateColumnAsKey
    {
    class Program
    {
        static void Main(string[] args)
        {
            MyContext ctx = new MyContext();
            ctx.CalendarItems.Add(new CalendarItem() { StartDate = DateTime.Now.Date });        // This works
            ctx.SaveChanges();
            ctx.CalendarItems.Add(new CalendarItem() { StartDate = DateTime.Now });     // This not !!
            ctx.SaveChanges();
            ctx.Dispose();
        }
        public class MyContext : DbContext
        {
            public DbSet<CalendarItem> CalendarItems { get;set; }
        }

        public class CalendarItem
        {
            [DatabaseGenerated( System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
            public int Id { get; set; }
            [Key, Column(Order = 1), DataType(DataType.Date)]
            public DateTime StartDate { get; set; }
        }
    }
}

我已经为bug #2185添加了一些细节。总之,当我们为INSERT操作创建SqlCommand时,我们为任何System类型的属性定义了一个DATETIME2类型的参数。但是出于兼容性原因,在默认情况下创建数据库模式时,我们将创建一个DateTime类型的列。

我们为插入生成的SQL如下所示:
INSERT [dbo].[CalendarItems]([StartDate]) VALUES (@0);
SELECT [Id] FROM [dbo].[CalendarItems] WHERE @@ROWCOUNT > 0 AND [StartDate] = @0; 

当你通过一个任意的系统。DataTime实例作为DATETIME2参数,最小有效数字将被保留,但是一旦DATETIME2参数的值存储在DATETIME列中,该值将被截断。

由于存储在StartDate中的值不再与参数@0的值匹配,第二条语句(即我们用来检测受影响的行的SELECT查询)将返回零行,命令将失败,事务将回滚,等等。

正如您已经发现的,可能的解决方法是:

  1. 使用代理身份键代替声明DateTime类型的键
  2. 对列
  3. 使用DateTime2
  4. 在发送到数据库之前截断内存中的值。

希望这有帮助,迭戈

相关内容

  • 没有找到相关文章

最新更新