【问题标题】:Creating entity with DateTime in primary key在主键中使用 DateTime 创建实体
【发布时间】:2015-11-22 14:05:54
【问题描述】:

假设我们在 SQL server 中有“EfTest”数据库和下表:

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();
    }

我们运行它,它在ctx.SaveChanges() 行上以DbUpdateConcurrencyException 失败,说:

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

显然,那里没有发生并发。 SQL Server 探查器报告以下查询由 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'DATETIME2DATETIMETS 的精度更高,WHERE 子句中的检查会阻止它找到刚刚插入的行。

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

我可以将TS 列设为DATETIME2 类型,这将解决问题,但我不想仅仅因为一些 EF 问题而浪费数据库空间。 我加倍检查了一下,DATETIMEDATETIME2 似乎都占用了 8 个字节,所以我想我是这样的。

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

还有其他选择吗?

【问题讨论】:

  • 也许有更好的解决方案,但您可以使用 Stored proc 作为最后的手段插入 db。
  • 您需要在模型中指定您使用复合主键,否则 EF 将永远无法工作,请参阅此帖子 stackoverflow.com/questions/14873169/…
  • 我使用数据库优先的方法,所以 EF 非常了解我有复合主键。

标签: c# sql-server entity-framework-5


【解决方案1】:

我最终使用 DATETIME2 作为列类型,因为没有空间折衷:DATETIMEDATETIME2 都占用 8 个字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多