实体框架SET IDENTITY_INSERT
当我们有一个自动递增的 ID 列时,有没有办法强制 EF 中新实体的 ID 值,即通过 EF 使用 SET IDENTITY_INSERT 行为?
我们的要求是,在填写或保存之前,我们的创建表单必须始终为我们在空表单上创建的对象显示一个新的、唯一的 ID。这个想法是,可以通过电话将该 ID 读给某人,然后用户可以在通话完成后填写并保存表单。我们可以通过在数据库中插入一个空行来保留一个 ID,但是我们有唯一的列和 FK;相反,我创建了一个“下一个 ID”表,为了安全起见,我们使用锁来增加该表,并且我也根据对象表中的顶部 ID 对其进行测试以小心。我们的想法是在我们写回实体时强制使用这个新 ID - 但我不知道如何让 EF 来做到这一点。
这可能吗——这只是我错过的事情吗?我认为 ID 甚至无法将其写入插入,因此我认为在 SaveChanges 周围手动调用 SET IDENTITY_INSERT 不会有帮助。
或者我必须做别的事情吗?我可以看到替代方案:
- 将 ID 列更改为不是身份并手动控制这一切:这里有一个表 ID 继承,因此这也可能很棘手。
- 将数据库 ID 和用户可见 ID 分开到一个单独的列中,并在那里记录我们的唯一 ID。
- 空行保留ID,如上;可能需要一些可空性更改,并修改我们的数据读取代码以忽略这些记录。
谢谢!这是 EF4(使用 EDMX 和生成的类而不是 POCO),并且在重要的情况下针对 SQL Server 2008。
Is there a way to force the ID value for a new entity in EF when we have an auto-incrementing ID column, i.e. use SET IDENTITY_INSERT behaviour through EF?
Our requirement is that our create form must always show a new, unique ID for the object we're creating on the empty form before it is filled in or saved. The idea is that this ID can be out read to someone over the phone and then the user can complete and save the form after the call is complete. We could reserve an ID by inserting an empty row into the database there and then, but we have unique columns and FKs; instead I've made a 'next ID' table that we increment with locks for safety, and I test this against the top ID in the object table too to be careful. The idea was to then force the use of this new ID when we write back the entity - but I can't see how to get EF to do it.
Is that possible - is it just something I've missed? I don't think the ID even makes it down to the insert so I don't think manually calling SET IDENTITY_INSERT around the SaveChanges would help.
Or do I have to do something else? I can see alternatives:
- Change our ID column to not be an identity and take manual control of it all: there's a table ID inheritance here so this is potentially tricky too.
- Separate DB ID and user-visible ID into a separate column, and record our unique ID there.
- Empty row to reserve the ID, as above; might need some nullability changes, and amending our data read code to ignore these records.
Thanks! This is EF4 (using an EDMX and generated classes not POCOs), and against SQL Server 2008 in case that matters.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为什么不使用 Guid 作为主键。与自动增量无关,没有并发陷阱等。您只需在创建表单时创建 Guid 即可。将其交给来电者并随后填写表格。当表格被取消时,没有问题。表单完成后,使用创建的 Guid 创建实体,设置实体对象的其他值,将其应用于 (a) 上下文和 SaveChanges()...
Why not use a Guid as primary key. Nothing to do with auto-increment, no concurrency pitfalls etc. You just create the Guid at the moment you create the form. Hand it over to a caller and fill in the form afterwards. When the form is cancelled, no problem. When the form is finished create the entity with the created Guid set the other values of the entity object, apply it to the (a) context and SaveChanges()...
不会改变架构的替代方案
您可以调用 context.SaveChanges() 并获取自动增量主键。该过程完成后,您可以提交交易。如果事务被取消或出现错误/异常,您可以随时回滚,这样行中就不会出现空洞/脏数据。我建议您使用单例模式并将相同的事务/上下文传递给任何方法或屏幕来完成该过程。
将空表单保存为草稿并保存 ID,然后继续使用信息编辑表单。完成后将表格保存为最终/准备就绪。如果您不继续保存表单,您可以随时回收草稿。
Alternatives that wont alter your schema
You can call context.SaveChanges() and get the autoincremented primary key. Once the process is completed you can commit the transaction. If the transaction is cancelled or there is an error/exception, you can always rollback so you wont have holes/dirty-data in your rows. I suggest you use the singleton pattern and pass the same transaction/context to whatever methods or screens to complete the process.
Save empty form as draft with saved ID, then proceed to edit the form with the information. Once complete save the form as final/ready. If you wont proceed to save the form, you can always recycle the draft.