从表中获取第一个未使用的Id?

时间:2015-11-10 20:30:08

标签: c# sql-server entity-framework linq entity-framework-6

在我们的数据库中,我们有一个缺少标识列的表。有一个Id列,但在输入记录时会手动填充。任何ID超过90,000的项目都会被保留,并在所有客户数据库中全局填充。

我正在使用Entity Framework构建一个工具来处理批量插入到此表中。我需要弄清楚找到第一个可用Id的最有效方法是什么(低于90,000),而不是迭代每一行。很可能在许多数据库中,有人只是选择了一个未被采用的随机数并用它来插入行。

我最好的办法是什么?

修改

在看到列出的一些解决方案后,我试图在Linq中复制SQL逻辑。我怀疑它是完美的,但它似乎非常快速和有效。

var availableIds = Enumerable.Range(1, 89999)
                       .Except(db.Table.Where(n => n.Id <= 89999)
                           .Select(n => n.TagAssociationTypeID))
                       .ToList();

2 个答案:

答案 0 :(得分:2)

您是否考虑过以下内容:

SELECT
    min(RN) AS FirstAvailableID
FROM (
    SELECT
        row_number() OVER (ORDER BY Id) AS RN,
        Id
    FROM
        YourTable
    ) x
WHERE
    RN <> Id

答案 1 :(得分:1)

回答您如何获得可用号码列表的隐含问题:轻松,列出所有可能的号码,然后删除正在使用的号码。

Source:

以下是通过实体框架

的方法
--This builds a list of numbers from 1 to 89999
SELECT TOP (89999) n = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
INTO #AvialableNumbers
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
OPTION (MAXDOP 1);

CREATE UNIQUE CLUSTERED INDEX n ON #AvialableNumbers(n)

--Start a seralizeable transaction so we can be sure no one uses a number
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
begin transaction

--Remove numbers that are in use.
delete #AvialableNumbers where n in (select Id from YourTable)

/*
Do your insert here using numbers from #AvialableNumbers
*/    

commit transaction