Sql server 不带标识列的LINQ插入

Sql server 不带标识列的LINQ插入,sql-server,linq-to-sql,identity-column,Sql Server,Linq To Sql,Identity Column,我使用的是LINQ,但我的数据库表没有标识列(尽管它们使用的是代理主键ID列) 这行吗 要获取表的标识值,有一个名为GetIDValueForOrangeTable()的存储过程,它查看SystemValues表并递增其中的ID。 有没有办法让LINQ在insert上从这个SystemValues表中获取ID值,而不是内置标识 顺便说一句,我认为这不是一个好主意,尤其是对于web应用程序。我想由于这个SystemValues查找,会有很多并发冲突。我的担心有道理吗 干杯 Duncan确保您可以使

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

这行吗

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

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

干杯
Duncan

确保您可以使用LINQ安全地完成此任务:

  • 将对底层SystemValues表的访问权包装在事务中的“GetIDValue…”函数中(而不是使用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
表不用于其他用途,那么它的性能应该是正常的。

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

但在web应用程序中这是否安全(且性能合理)?web唯一有效的事务级别是乐观锁定,不是吗?如果我错了,请纠正我!非常感谢,非常感谢,我会考虑一下。然而,我们可能会有成千上万的用户在短时间内访问这个数据库,所以我们必须认真考虑性能!您无需访问
SystemTables
两次即可执行此操作,就像第二种方法一样