Entity Framework 格式 DateTime SQL 参数不带毫秒用于乐观并发
Entity Framework formats DateTime SQL parameter without milliseconds for optimistic concurrency
我正在尝试在 Entity Framework 中使用具有乐观并发的 DateTime LastModifiedDate 列(可能会将其升级到 DateTime2。)我已将并发模式设置为固定。但是当我检索一个实体、更改一列并尝试保存时,出现并发异常。
存储的 LastModifiedDate 是 2017-01-04 21:16:55.283
但查看 SQL Entity Framework 正在为更新生成:
UPDATE [dbo].[Facilities]
SET [Password] = @0
WHERE (([pk_FacilityID] = @1) AND ([LastModifiedDate] = @2))
-- @0: 'bz0dkK+smlat9psrIrbyXkxjpcXcDK1DeUiha7jCRkU=' (Type = String, Size = 255)
-- @1: '6801bdcf-266d-46bd-b15e-dac21116208d' (Type = Guid)
-- @2: '1/4/2017 9:16:55 PM' (Type = DateTime2)
请注意,它正在为 @2
传递格式化的 DateTime 字符串,其中不包括毫秒。当然,如果它没有传递与它检索到的相同的值,它就不匹配!我已经验证在运行时,.NET DateTime 确实包含 0.283 秒。请告诉我有一种方法可以传递全部价值。为什么它会这样,我如何更改它以包括毫秒?
-- @2: '1/4/2017 9:16:55 PM' (Type = DateTime2)
这不是实际发送的参数值。那只是日志记录,它省去了小数秒。有问题,但不是。
如果您进行概要分析,您应该会看到类似这样的内容,其中显示了参数类型和值的详细信息。
exec sp_executesql N'UPDATE [dbo].[Facilities]
SET [Name] = @0
WHERE (([FacilityId] = @1) AND ([LastModified] = @2))
',N'@0 nvarchar(max) ,@1 int,@2 datetime2(7)',@0=N'newName',@1=1,@2='2017-08-31 15:45:55.3030000'
发生的情况是 datetime2(7) 值不是往返于 datetime 的往返转换。最简单的解决方法就是对 table 列使用 datetime2(7)。如果要使用该列进行乐观并发控制,无论如何都需要额外的精度。
所以像这样:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace Ef6Test
{
public class Facility
{
public int FacilityId { get; set; }
public string Name { get; set; }
[ConcurrencyCheck(),Column(TypeName ="datetime2")]
public DateTime LastModified { get; set; }
}
class Db : DbContext
{
public DbSet<Facility> Facilities { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<Db>());
using (var db = new Db())
{
var f = db.Facilities.Add(new Facility() { LastModified = DateTime.Now, Name = "Faclity1" });
db.SaveChanges();
}
using (var db = new Db())
{
var f = db.Facilities.First();
f.Name = "newName";
db.SaveChanges();
}
Console.ReadKey();
}
}
}
我正在尝试在 Entity Framework 中使用具有乐观并发的 DateTime LastModifiedDate 列(可能会将其升级到 DateTime2。)我已将并发模式设置为固定。但是当我检索一个实体、更改一列并尝试保存时,出现并发异常。
存储的 LastModifiedDate 是 2017-01-04 21:16:55.283
但查看 SQL Entity Framework 正在为更新生成:
UPDATE [dbo].[Facilities]
SET [Password] = @0
WHERE (([pk_FacilityID] = @1) AND ([LastModifiedDate] = @2))
-- @0: 'bz0dkK+smlat9psrIrbyXkxjpcXcDK1DeUiha7jCRkU=' (Type = String, Size = 255)
-- @1: '6801bdcf-266d-46bd-b15e-dac21116208d' (Type = Guid)
-- @2: '1/4/2017 9:16:55 PM' (Type = DateTime2)
请注意,它正在为 @2
传递格式化的 DateTime 字符串,其中不包括毫秒。当然,如果它没有传递与它检索到的相同的值,它就不匹配!我已经验证在运行时,.NET DateTime 确实包含 0.283 秒。请告诉我有一种方法可以传递全部价值。为什么它会这样,我如何更改它以包括毫秒?
-- @2: '1/4/2017 9:16:55 PM' (Type = DateTime2)
这不是实际发送的参数值。那只是日志记录,它省去了小数秒。有问题,但不是。
如果您进行概要分析,您应该会看到类似这样的内容,其中显示了参数类型和值的详细信息。
exec sp_executesql N'UPDATE [dbo].[Facilities]
SET [Name] = @0
WHERE (([FacilityId] = @1) AND ([LastModified] = @2))
',N'@0 nvarchar(max) ,@1 int,@2 datetime2(7)',@0=N'newName',@1=1,@2='2017-08-31 15:45:55.3030000'
发生的情况是 datetime2(7) 值不是往返于 datetime 的往返转换。最简单的解决方法就是对 table 列使用 datetime2(7)。如果要使用该列进行乐观并发控制,无论如何都需要额外的精度。
所以像这样:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace Ef6Test
{
public class Facility
{
public int FacilityId { get; set; }
public string Name { get; set; }
[ConcurrencyCheck(),Column(TypeName ="datetime2")]
public DateTime LastModified { get; set; }
}
class Db : DbContext
{
public DbSet<Facility> Facilities { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<Db>());
using (var db = new Db())
{
var f = db.Facilities.Add(new Facility() { LastModified = DateTime.Now, Name = "Faclity1" });
db.SaveChanges();
}
using (var db = new Db())
{
var f = db.Facilities.First();
f.Name = "newName";
db.SaveChanges();
}
Console.ReadKey();
}
}
}