在主键中创建带有 DateTime 的实体
Creating entity with DateTime in primary key
假设我们有 "EfTest" 数据库,在 SQL 服务器中有以下 table:
create table Test
(
Id INT NOT NULL IDENTITY(1,1),
TS DATETIME NOT NULL
PRIMARY KEY (TS, Id)
)
我们想用 EF(在我的例子中是 EF 5)添加东西。我们在示例项目中从数据库创建 edmx 文件并编写以下代码:
static void Main(string[] args)
{
var ctx = new EFTestEntities();
var t = new Test();
t.TS = DateTime.Now;
ctx.Tests.Add(t);
ctx.SaveChanges();
}
我们 运行 它失败了 DbUpdateConcurrencyException
在 ctx.SaveChanges()
行,说:
Store update, insert, or delete statement affected an unexpected
number of rows (0). Entities may have been modified or deleted since
entities were loaded. Refresh ObjectStateManager entries.
显然,那里没有发生并发。 SQL 服务器分析器报告以下查询是 运行 由 EF:
exec sp_executesql N'insert [dbo].[Test]([TS])
values (@0)
select [Id]
from [dbo].[Test]
where @@ROWCOUNT > 0 and [Id] = scope_identity() and [TS] = @0',N'@0 datetime2(7)',@0='2015-08-27 18:29:45.1025442'
问题出在这里:@0 datetime2(7),@0='2015-08-27 18:29:45.1025442'
。 DATETIME2
比 DATETIME
精度更高,TS
检查 WHERE
子句可防止它找到刚刚插入的行。
问题:抛开为什么我有 DATETIME
列作为 PK 的一部分的原因,我如何让 EF 插入行而不抛出异常?
我可以将 TS
列设为 DATETIME2
类型,这样可以解决问题,但我不想浪费数据库 space因为一些 EF 问题。 我仔细检查了一下,似乎 DATETIME
and DATETIME2
都占用了 8 个字节,所以我想我是那样做的。
我可以在文本编辑器中编辑 .edmx
文件,让它认为主键只是 Id
列(所以 EF 不会使用 TS
来查找 Id
插入后),但 VS 将在我下次从数据库更新实体时覆盖我的编辑。
还有其他选择吗?
我最终使用 DATETIME2
作为列类型,因为没有 space 权衡:DATETIME
和 DATETIME2
都占用 8 个字节。
假设我们有 "EfTest" 数据库,在 SQL 服务器中有以下 table:
create table Test
(
Id INT NOT NULL IDENTITY(1,1),
TS DATETIME NOT NULL
PRIMARY KEY (TS, Id)
)
我们想用 EF(在我的例子中是 EF 5)添加东西。我们在示例项目中从数据库创建 edmx 文件并编写以下代码:
static void Main(string[] args)
{
var ctx = new EFTestEntities();
var t = new Test();
t.TS = DateTime.Now;
ctx.Tests.Add(t);
ctx.SaveChanges();
}
我们 运行 它失败了 DbUpdateConcurrencyException
在 ctx.SaveChanges()
行,说:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
显然,那里没有发生并发。 SQL 服务器分析器报告以下查询是 运行 由 EF:
exec sp_executesql N'insert [dbo].[Test]([TS])
values (@0)
select [Id]
from [dbo].[Test]
where @@ROWCOUNT > 0 and [Id] = scope_identity() and [TS] = @0',N'@0 datetime2(7)',@0='2015-08-27 18:29:45.1025442'
问题出在这里:@0 datetime2(7),@0='2015-08-27 18:29:45.1025442'
。 DATETIME2
比 DATETIME
精度更高,TS
检查 WHERE
子句可防止它找到刚刚插入的行。
问题:抛开为什么我有 DATETIME
列作为 PK 的一部分的原因,我如何让 EF 插入行而不抛出异常?
我可以将 我仔细检查了一下,似乎 TS
列设为 DATETIME2
类型,这样可以解决问题,但我不想浪费数据库 space因为一些 EF 问题。DATETIME
and DATETIME2
都占用了 8 个字节,所以我想我是那样做的。
我可以在文本编辑器中编辑 .edmx
文件,让它认为主键只是 Id
列(所以 EF 不会使用 TS
来查找 Id
插入后),但 VS 将在我下次从数据库更新实体时覆盖我的编辑。
还有其他选择吗?
我最终使用 DATETIME2
作为列类型,因为没有 space 权衡:DATETIME
和 DATETIME2
都占用 8 个字节。