为什么我无法使用Entity Framework保存当前的DateTime.Now
using (var transaction = new TransactionScope()) { using (var db = new MyEntities()) { var newGroup = new Groups { GroupDate = DateTime.Now, GroupName = "someName" }; db.Groups.Add(newGroup); db.SaveChanges(); } transaction.Complete(); }
GroupId和GroupDate是PK,GroupId是Identity(步骤= 1)而GroupDate不是
任何人都可以告诉我为什么在使用像这样的简单代码时发生这种exception以及如果可能的话如何关闭乐观并发更新
存储更新,插入或删除语句会影响意外的行数(0)。 自实体加载后,实体可能已被修改或删除。 刷新ObjectStateManager条目。
它很可能是.NET DateTime
类型的不同精度和您在SQL Server中使用的列类型的问题 – 可能是datetime
。
使用SaveChanges
发送到数据库的INSERT语句如下所示:
exec sp_executesql N'insert [dbo].[Groups]([GroupDate], [GroupName]) values (@0, @1) select [GroupId] from [dbo].[Groups] where @@ROWCOUNT > 0 and [GroupId] = scope_identity() and [GroupDate] = @0', N'@0 datetime2(7),@1 nvarchar(50)', @0='2013-09-01 14:21:44.5156250',@1=N'someName'
.NET DateTime
在小数点后存储7位数: .5156250
。 但是SQL datetime
类型无法存储它,因为它具有较低的精度,并且在存储值后会切断一些数字。 因此, where
子句中的比较[GroupDate] = @0
返回false
,EF获取没有存储任何内容的信息(尽管实际上已执行INSERT),取消事务并抛出exception。
据我所知,您只能通过以下更改之一解决此问题:
- 从主键中删除
GroupDate
非键列 - 或者将SQL Server中的列类型更改为
datetime2(7)
,其精度与.NETDateTime
类型相同 -
或者为
GroupDate
提供较低的精度,以便可以将值完全存储在SQLdatetime
类型中而不会被截断,例如仅使用秒精度且毫秒为0
:var now = DateTime.Now; var date = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); var newGroup = new Groups { GroupDate = date, GroupName = "someName" };
(可能有一种更聪明的方法可以从给定的
DateTime
值中删除毫秒,而不是上面的代码,但我现在找不到。)
不要关闭Optmistic Concurrency Updates ,您将隐藏问题而不是修复它。 请执行下列操作:
using (var db = new MyEntities()) { using (var transaction = new TransactionScope()) { var newGroup = new Groups { GroupDate = DateTime.Now, GroupName = "someName" }; db.Groups.Add(newGroup); db.SaveChanges(); transaction.Complete(); } }
不同的是你现在在DBContext中创建TranscationScope我希望这能解决你的问题。