0

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

这能行吗?

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

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

干杯邓肯

4

2 回答 2

1

当然,您也可以使用 LINQ 安全地完成这项工作:

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

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

马克

更新:

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

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表不用于其他用途,那么它应该可以执行。

于 2009-08-11T16:14:20.030 回答
1

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

于 2009-08-11T17:18:00.510 回答