不带 IDENTITY 列的 LINQ 插入

发布于 2024-07-30 19:12:29 字数 338 浏览 7 评论 0原文

我正在使用 LINQ,但我的数据库表没有 IDENTITY 列(尽管它们使用代理主键 ID 列)

这可以工作吗?

为了获取表的标识值,有一个名为 GetIDValueForOrangeTable() 的存储过程,它查看 SystemValues 表并递增其中的 ID。 有什么方法可以让 LINQ 在插入时从该 SystemValues 表获取 ID 值,而不是内置的 IDENTITY 吗?

顺便说一句,我认为这不是一个好主意,尤其是对于 Web 应用程序而言。 我想由于这个 SystemValues 查找,将会出现很多并发冲突。 我的担心有道理吗?

干杯 邓肯

I'm using LINQ, but my database tables do not have an IDENTITY column (although they are using a surrogate Primary Key ID column)

Can this work?

To get the identity values for a table, there is a stored procedure called GetIDValueForOrangeTable(), which looks at a SystemValues table and increments the ID therein.
Is there any way I can get LINQ to get the ID value from this SystemValues table on an insert, rather than the built in IDENTITY?

As an aside, I don't think this is a very good idea, especially not for a web application. I imagine there will be a lot of concurrency conflicts because of this SystemValues lookup. Am I justified in my concern?

Cheers
Duncan

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

十秒萌定你 2024-08-06 19:12:29

你的担心是非常有道理的。 如果两个用户尝试同时插入,则两个用户可能会获得相同的编号,除非您按照 marc_s 的描述进行操作并将其放入事务中。 但是,如果事务没有环绕整个插入以及包含 id 值的表,那么如果外部插入失败(它获得了一个值,但由于某些其他原因没有插入一个值),您可能仍然会有间隙。记录)。 由于大多数人这样做是为了避免差距(这在大多数情况下是不必要的要求),这使得生活变得更加复杂,并且仍然可能无法实现结果。 使用身份字段几乎总是更好的选择。

You are very justified in your concern. If two users try to insert at the sametime, both might be given the same number unless you do as described by marc_s and put the thing in a transaction. However, if the transaction doesn't wrap around your whole insert as well as the table that contains the id values, you may still have gaps if the outer insert fails (It got a value but then for some other reason didn't insert a record). Since most people do this to avoid gaps (something that is in most cases an unnecessary requirement) it makes life more complicated and still may not achieve the result. Using an identity field is almost always a better choice.

零度° 2024-08-06 19:12:29

当然,您也可以使用 LINQ 实现这一点,而且也安全:

  • 将对底层 SystemValues 表的访问包装在 TRANSACTION 中的“GetIDValue.....()”函数中(而不是使用 READUNCOMMITTED 隔离级别!),然后一个且只有一个用户可以在任何给定时间访问该表,并且您应该能够
  • 在保存实体之前安全地分发来自 LINQ 的存储过程的 ID 调用,并在处理新实体时存储 ID(如果 ID尚未设置)
  • 将您的实体存储在数据库中

这应该可以工作 - 不确定它是否比让数据库处理工作更快、更有效 - 但它应该工作 - 并且安全。

Marc

更新:

这样的东西(适应您的需求)将安全地工作:

CREATE PROCEDURE dbo.GetNextTableID(@TableID INT OUTPUT)
AS BEGIN
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED

    BEGIN TRANSACTION 

    UPDATE SystemTables
    SET MaxTableID = MaxTableID + 1
    WHERE ........ 

    SELECT
        @TableID = MaxTableID 
    FROM    
        dbo.SystemTables

    COMMIT TRANSACTION
END

至于性能 - 只要您有合理数量(可能少于 50 个)的并发用户,并且只要这个 SystemTables 表没有用于其他用途,那么它应该执行正常。

Sure you can make this work with LINQ, and safely, too:

  • wrap the access to the underlying SystemValues table in the "GetIDValue.....()" function in a TRANSACTION (and not with the READUNCOMMITTED isolation level!), then one and only one user can access that table at any given time and you should be able to safely distribute ID's
  • call that stored proc from LINQ just before saving your entity and store the ID if you're dealing with a new entity (if the ID hasn't been set yet)
  • store your entity in the database

That should work - not sure if it's any faster and any more efficient than letting the database handle the work - but it should work - and safely.

Marc

UPDATE:

Something like this (adapt to your needs) will work safely:

CREATE PROCEDURE dbo.GetNextTableID(@TableID INT OUTPUT)
AS BEGIN
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED

    BEGIN TRANSACTION 

    UPDATE SystemTables
    SET MaxTableID = MaxTableID + 1
    WHERE ........ 

    SELECT
        @TableID = MaxTableID 
    FROM    
        dbo.SystemTables

    COMMIT TRANSACTION
END

As for performance - as long as you have a reasonable number (less than 50 maybe) of concurrent users, and as long as this SystemTables tables isn't used for much else, then it should perform OK.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文