是否可以在将身份字段值保存到实体框架之前获取它

2024-03-21

我有一个客户和销售表

CUSTOMER
--------------
Id (int auto increment)
Name

SALES
---------------
Id (int auto increment)
CustomerId (int)
OrderTotal (decimal)

有了Guid我就可以做到这一点。

dbTransaction = dbContext.Database.BeginTransaction(isolationLevel);

var customer = new Customer()
{
  Id = Guid.NewGuid(),
  Name = "John Doe"
};

var sales = new Sales() 
{
  Id = Guid.NewGuid(),
  CustomerId = customer.Id,
  OrderTotal = 500
};

dbContext.SaveChanges();
dbTransaction.Commit();

如果我的主键是 int (带有 DatabaseGenerateOption.Identity),我该如何执行此操作?


你不能。进入的IDIDENTITY列是由数据库在插入时生成的,所有规避该列并自行确定 ID 的“技巧”可能都有缺陷。

简短回答:如果您希望在保存之前对生成 ID 有发言权,请使用 GUID (UNIQUEIDENTIFIER), or a SEQUENCE(如果您使用的是 SQL Server 2012 或更高版本)。

为什么你不应该自己计算下一个免费 ID:

甚至不要考虑运行诸如context.Customers.Max(c => c.Id) + 1作为一个可行的解决方案,因为您总是有可能进行并发数据库访问:在您读取下一个“空闲”ID 之后但在存储实体之前,另一个进程或线程可能会将新实体持久保存到同一个表中。计算下一个空闲 ID 很容易发生冲突,除非获取 ID、用它做某事以及使用该 ID 存储实体的整个操作都是原子的。这可能需要数据库中的表锁,这可能效率低下。

(即使使用时也存在同样的问题SEQUENCEs,SQL Server 2012 中引入的新功能。) (我错了 https://stackoverflow.com/questions/29740705/is-it-possible-to-get-identity-field-value-before-saving-it-in-entity-framework/29740773?noredirect=1#comment47615961_29740773;见答案末尾。)

可能的解决方案:

  1. 如果您需要在保存对象之前确定该对象的 ID,则不要使用出现在IDENTITY柱子。保留 GUID,因为你极不可能与这些发生任何碰撞。

  2. 无需二选一or另一个:你实际上可以鱼与熊掌兼得!没有什么可以阻止你拥有两个 ID 列,一个由您在外部确定(GUID),另一个由数据库内部确定(GUID)IDENTITY柱子);请参阅博客文章“CQS 与服务器生成的 ID” http://blog.ploeh.dk/2014/08/11/cqs-versus-server-generated-ids/作者:Mark Seemann,更详细地了解了这个想法。以下是示例的总体思路:

    CREATE TABLE Foos
    (
        FooId INT IDENTITY NOT NULL PRIMARY KEY CLUSTERED,
     -- ^^^^^ assigned by the DBMS upon insertion. Mostly for DB-internal use.
        Id UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE DEFAULT (NEWID()),
     -- ^^ can be dictated and seen by the users of your DB. Mostly for DB-external use.
        …
    );
    
    CREATE TABLE FooBars
    (
        FooId INT NOT NULL FOREIGN KEY REFERENCES Foos (FooId),
     --   use DB-internal ID in foreign key constraints ^^^^^
        …
    );
    
    CREATE VIEW PublicFoos AS
    SELECT Id, … FROM Foos;
    --     ^^ publish the public ID for users of your DB
    

    (确保遵守一些约定,以一致地命名内部和公共 ID 字段名称。)

  3. SEQUENCEs是 SQL Server 2012 中引入的一项功能,是替代IDENTITY柱子。它们会自动增加,并且在使用以下方式获取下一个免费 ID 时,您将得到一个唯一的编号:NEXT VALUE FOR SomeSequence https://technet.microsoft.com/en-us/library/ff878370.aspx。用例之一MSDN 上提到过 https://msdn.microsoft.com/de-ch/library/ff878058.aspx are:

    在以下场景中使用序列而不是标识列: [...] 应用程序在插入表之前需要一个数字。

    一些注意事项:

    • 获取下一个序列值将需要与数据库进行额外的往返。

    • 与身份列一样,序列可以重置/重新播种,因此有理论的ID冲突的可能性。最好never如果可以的话,重新播种身份列和序列。

    • 如果您使用以下命令获取下一个空闲序列值NEXT VALUE FOR,但随后决定不使用它,这将导致您的 ID 出现“间隙”。常规(非顺序)GUID 显然不会出现间隙,因为它们没有固有的顺序。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以在将身份字段值保存到实体框架之前获取它 的相关文章

  • 为什么我不能用 `= delete;` 声明纯虚函数?

    Intro 纯虚函数使用通用语法声明 virtual f 0 然而 自 c 11 以来 有一种方法可以显式地传达non existence 特殊 成员函数的 Mystruct delete eg default constructor Q
  • 如何在 Android NDK 中创建新的 NativeWindow 而无需 Android 操作系统源代码?

    我想编译一个 Android OpenGL 控制台应用程序 您可以直接从控制台启动 Android x86 运行 或者从 Android x86 GUI 内的 Android 终端应用程序运行 这个帖子 如何在 Android NDK 中创
  • Clang 编译器 (x86):80 位长双精度

    我正在尝试在 x86 Windows 平台上使用本机 80 位长双精度 海湾合作委员会选项 mlong double 80 https gcc gnu org onlinedocs gcc x86 Options html似乎不适用于 cl
  • 构造函数中显式关键字的使用

    我试图了解 C 中显式关键字的用法 并查看了这个问题C 中的explicit关键字是什么意思 https stackoverflow com questions 121162 但是 那里列出的示例 实际上是前两个答案 对于用法并不是很清楚
  • ASP MVC:服务应该返回 IQueryable 的吗?

    你怎么认为 你的 DAO 应该返回一个 IQueryable 以便在你的控制器中使用它吗 不 您的控制器根本不应该处理任何复杂的逻辑 保持苗条身材 模型 而不是 DAO 应该将控制器返回给视图所需的所有内容 我认为在控制器类中看到查询 甚至
  • 如何从网站下载 .EXE 文件?

    我正在编写一个应用程序 需要从网站下载 exe 文件 我正在使用 Visual Studio Express 2008 我正在使用以下代码 private void button1 Click object sender EventArgs
  • 在非活动联合成员上使用“std::addressof”是否定义明确[重复]

    这个问题在这里已经有答案了 下面的代码是尝试实现constexpr的版本offsetof在 C 11 中 它可以在 gcc 7 2 0 和 clang 5 0 0 中编译 这取决于申请std addressof工会非活跃成员的成员 这是明确
  • 基于xsd模式生成xml(使用.NET)

    我想根据我的 xsd 架构 cap xsd 生成 xml 文件 我找到了这篇文章并按照说明进行操作 使用 XSD 文件生成 XML 文件 https stackoverflow com questions 6530424 generatin
  • 如何重置捕获像素的值

    我正在尝试创建一个 C 函数 该函数返回屏幕截图位图中每四个像素的 R G 和 B 值 这是我的代码的一部分 for int ix 4 ix lt 1366 ix ix 4 x x 4 for int iy 3 iy lt 768 iy i
  • 如何从 Laravel 执行存储过程

    我需要在表单提交数据后执行存储过程 我让存储过程按照我想要的方式工作 并且我的表单正常工作 我只是不知道从 laravel 5 执行 sp 的语句 它应该是这样的 执行 my stored procedure 但我似乎在网上找不到类似的东西
  • 如何在c#中的内部类中访问外部类的变量[重复]

    这个问题在这里已经有答案了 我有两个类 我需要声明两个类共有的变量 如果是嵌套类 我需要访问内部类中的外部类变量 请给我一个更好的方法来在 C 中做到这一点 示例代码 Class A int a Class B Need to access
  • 如何使用 php 在 sql 查询中转义引号?

    我有一个疑问 sql SELECT CustomerID FROM tblCustomer WHERE EmailAddress addslashes POST username AND Password addslashes POST p
  • 如何挤出平面 2D 网格并赋予其深度

    我有一组共面 连接的三角形 即二维网格 现在我需要将其在 z 轴上挤出几个单位 网格由一组顶点定义 渲染器通过与三角形数组匹配来理解这些顶点 网格示例 顶点 0 0 0 10 0 0 10 10 0 0 10 0 所以这里我们有一个二维正方
  • 获取 2 个数据集 c# 中的差异

    我正在编写一个简短的算法 它必须比较两个数据集 以便可以进一步处理两者之间的差异 我尝试通过合并这两个数据集并将结果更改放入新的数据集来实现此目标 我的方法如下所示 private DataSet ComputateDiff DataSet
  • 如何一步步遍历目录树?

    我发现了很多关于遍历目录树的示例 但我需要一些不同的东西 我需要一个带有某种方法的类 每次调用都会从目录返回一个文件 并逐渐遍历目录树 请问我该怎么做 我正在使用函数 FindFirstFile FindNextFile 和 FindClo
  • g++ 对于看似不相关的变量“警告:迭代...调用未定义的行为”

    考虑以下代码strange cpp include
  • 为什么拆箱枚举会产生奇怪的结果?

    考虑以下 Object box 5 int int int box int 5 int nullableInt box as int nullableInt 5 StringComparison enum StringComparison
  • 结构体指针的动态数组

    我必须使用以下代码块来完成学校作业 严格不进行任何修改 typedef struct char firstName char lastName int id float mark pStudentRecord pStudentRecord
  • Googletest:如何异步运行测试?

    考虑到一个包含数千个测试的大型项目 其中一些测试需要几分钟才能完成 如果按顺序执行 整套测试需要一个多小时才能完成 通过并行执行测试可以减少测试时间 据我所知 没有办法直接从 googletest mock 做到这一点 就像 async选项
  • 实例化 Microsoft.Office.Interop.Excel.Application 对象时出现错误:800700c1

    实例化 Microsoft Office Interop Excel Application 以从 winforms 应用程序生成 Excel 时 出现以下错误 这之前是有效的 但突然间它停止工作了 尽管代码和 Excel 版本没有变化 我

随机推荐