У меня есть база данных счетов, которая содержит ID IDENTITY, который SQL Server автоматически генерирует с шагом один (+1) каждый раз, когда новая запись создается с помощью вставки LINQ.
Код, который я сейчас использую для создания новой записи, размещен ниже, а инкрементный идентификатор автоматически генерируется SQL Server.
public async Task<IActionResult> Create([Bind(
"PurchaseOrder,InvDate,DelDate,PaidDate,AgentName,FullName,FirstName, LastName,CustId,CompanyName,ClientRole,Email,Phone,Address," +
"City,State,Zip,Country,ProdCode,Description,Quantity,UnitPrice,LineTotal,OrderTotal,Tax,Discount,Credit," +
"Shipping,GrandTotal,Deposit,AmtDue,DiscAmt,Notes,Published,Year,Expenses,ProjectDescription,ClientProvision")]
CreateNewOrderViewModel cnq)
{
int invId;
try
{
await _context.AddAsync(cnq);
await _context.SaveChangesAsync();
}
catch (InvalidCastException e)
{
ViewBag.Result = $"Database insert failed with: {e}";
return View();
}
}
Моя проблема связана с идентификатором SQL Server IDENTITY. Каждый раз, когда сервер перезагружается, мое значение ID IDENTITY увеличивается в 1000 раз вместо значения по умолчанию 1, что, например, изменяет/увеличивает следующую запись, которую я создал, в 1000 раз. Следовательно, если моя последняя запись было 1001, следующая созданная запись будет 2001, а не 1002. Такое поведение сохраняется каждый раз, когда сервер обновляется и требует перезагрузки. Я искал ответ и обнаружил, что проблема связана с ошибкой SQL Server, основанной на кэшированном протоколе, который запоминает последние значения идентификаторов.
Поскольку я нахожусь на сервере общего хостинга и не имею полного контроля над базой данных, у меня есть только DBO для моей собственной базы данных. Мне было интересно, есть ли у меня способ использовать LINQ для создания добавочного значения для нового столбца InvID, которое я затем могу использовать в качестве идентификатора записи вместо значения, сгенерированного SQL Server.
@mxmissile OP верен, перезапуск службы повлияет на последовательности идентификации. stackoverflow.com/questions/14162648/…
@DerrickMoeller очень интересно, к сожалению, я все еще использую 2008 год, он был представлен в 2012 году. Спасибо за предупреждение.
ОП, какое это имеет значение, если ваши идентификаторы не ++ в последовательности? Идентификаторы базы данных никогда должны использоваться для бизнес-логики. Если вы используете это для счета # или чего-то еще, вам лучше придумать свою собственную схему нумерации, пусть база данных сделает свое дело.
@mxmissile, я согласен и решил обновить базу данных перед каждой новой записью, как я написал ниже.





Если у вас нет контроля над базой данных для обработки проблема с идентификацией сервера sql, вам нужно вручную прочитать наибольшее Id из таблицы и увеличить его на 1 для новой записи.
Пример кода для получения последнего Id:
int lastId = _context.TableA.OrderByDescending(t => t.Id).FirstOrDefault().Id;
int newId = lastId + 1;
// Add the new record with newId
Да, это сработало бы, и я могу это сделать, если бы использовал хранимую процедуру для создания новых записей. Однако я не очень хорошо знаком с LINQ, поэтому не знаю, как это сделать. Если у кого-то есть какие-либо идеи о том, как использовать LINQ, как я делаю выше, для создания новых записей и вставки нового InvID из значения переменной, опубликуйте его. спасибо
Я не думаю, что смогу добавить новый идентификатор, когда SQL Server уже имеет столбец идентификатора в качестве столбца IDENTITY, поскольку он создается автоматически.
Это атомарно?
Вы можете добавить следующий атрибут к свойству модели, чтобы отключить автоматически сгенерированную идентификацию: [System.ComponentModel.DataAnnotations.DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]
Прочитав несколько рекомендаций, я решил проверить и повторно заполнить идентификатор перед выполнением запроса LINQ.
using (var connection = new SqlConnection(_data.DATA))
{
connection.Open();
try
{
var seed = new SqlCommand("CreateIDSeed", connection)
{
CommandType = CommandType.StoredProcedure
};
seed.ExecuteNonQuery();
await _context.AddAsync(cnq);
await _context.SaveChangesAsync();
}
catch (InvalidCastException e)
{
ViewBag.Result = $"Database insert failed with: {e}";
return View();
}
}
Где CreateIDSeed выглядит так:
CREATE PROCEDURE [dbo].[CreateIDSeed]
AS
BEGIN
SET NOCOUNT ON;
declare @newId int
select @newId = max(ID) from dbo.CreateNewOrderViewModel
DBCC CheckIdent('dbo.CreateNewOrderViewModel', RESEED, @newId)
END
GO
Я попытался вставить несколько тестовых записей, и, похоже, это работает, но я узнаю больше, когда сервер будет перезагружен.
Что-то здесь не так, перезагрузка не должна иметь ничего общего с последовательностью Id. Можете ли вы опубликовать свое определение таблицы?