Majid
Majid

Reputation: 14243

Linq statement for returning next ID

I have list of Books with PK of Id and some of Books may deleted. for example list with this Ids:

1 2 5 6 8

now I need a linq statement to return next insertion Id (in example "3")

I tried this code but it always return "1":

 public int GetNextRecordId()
    {
        List<Book> books = getAll();
        int counted = books.Count();
        foreach (Book b in books)
        {
            if (books.Where(book => book.Id == (b.Id + 1)) == null)
                return b.Id + 1;
        }
        return 1;
    }

How to fix this?

Upvotes: 1

Views: 817

Answers (3)

Ian Mercer
Ian Mercer

Reputation: 39277

If you have a large number of books you probably can't hold them all in memory like that. And you certainly don't want to be doing a loop over them with a Where clause in it iterating over them again. You would be better off reading them sequentially to look for a gap like this:-

public int GetNextRecordId()
{
    // Cannot load all books into memory ...
    IEnumerable<Book> books = dataContext.Books.OrderBy(b => b.Id);

    int index = 0;
    foreach (var book in books)
    {
      index++;
      if (index < book.Id) return index;
    }
    return index;
}

Upvotes: 2

Reza ArabQaeni
Reza ArabQaeni

Reputation: 4907

I suggest this linq query, if this query run on linq to entites, cost of query is very low:

var id = books.Select(p => p.Id  + 1).Except(books.Select(p=>p.Id)).First();

Upvotes: 1

Gjeltema
Gjeltema

Reputation: 4156

One thing I notice right away is that this will never be true:

books.Where(book => book.Id == (b.Id + 1)) == null

The Where call returns an empty enumerable if it finds no matches. Start from there.

Try this instead:

!books.Where(book => book.Id == (b.Id + 1)).Any()

Upvotes: 5

Related Questions