在主键中创建带有 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();
    }

我们 运行 它失败了 DbUpdateConcurrencyExceptionctx.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'DATETIME2DATETIME 精度更高,TS 检查 WHERE 子句可防止它找到刚刚插入的行。

问题:抛开为什么我有 DATETIME 列作为 PK 的一部分的原因,我如何让 EF 插入行而不抛出异常?

我可以将 TS 列设为 DATETIME2 类型,这样可以解决问题,但我不想浪费数据库 space因为一些 EF 问题。 我仔细检查了一下,似乎 DATETIME and DATETIME2 都占用了 8 个字节,所以我想我是那样做的。

我可以在文本编辑器中编辑 .edmx 文件,让它认为主键只是 Id 列(所以 EF 不会使用 TS 来查找 Id 插入后),但 VS 将在我下次从数据库更新实体时覆盖我的编辑。

还有其他选择吗?

我最终使用 DATETIME2 作为列类型,因为没有 space 权衡:DATETIMEDATETIME2 都占用 8 个字节。