没有IDENTITY列的LINQ插入

时间:2009-08-11 16:08:38

标签: sql-server linq-to-sql identity-column

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

这可以吗?

要获取表的标识值,有一个名为GetIDValueForOrangeTable()的存储过程,它查看SystemValues表并在其中递增ID。 有没有办法让LINQ从插件上的SystemValues表中获取ID值,而不是内置的IDENTITY?

顺便说一句,我认为这不是一个好主意,尤其不适用于Web应用程序。我想由于这个SystemValues查找会有很多并发冲突。我对自己的担忧是否合理?

干杯 邓肯

2 个答案:

答案 0 :(得分:1)

当然,您可以使用LINQ安全地工作:

  • 在TRANSACTION中的“GetIDValue .....()”函数中包装对底层SystemValues表的访问(而不是READUNCOMMITTED隔离级别!),然后一个且只有一个用户可以访问该表给定时间,您应该能够安全地分发ID
  • 在保存您的实体之前从LINQ调用存储过程并在您处理新实体时存储该ID(如果尚未设置该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表没有用于其他许多,那么它应该执行正常。

答案 1 :(得分:1)

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