В этом примере консольного приложения я хочу обновить строку в таблице, а затем вставить другую строку в той же таблице.
Таблица выглядит так
CREATE TABLE [dbo].[Basket2](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserId] [int] NULL
) ON [PRIMARY]
CREATE UNIQUE NONCLUSTERED INDEX [IX_Basket] ON [dbo].[Basket2]
(
[UserId] ASC
)
Таким образом, в основном пользователь не может иметь 2 корзины.
По причинам, не входящим в этот пост, корзины нельзя удалять из таблицы. Поэтому, когда пользователю нужна новая корзина, старая просто устанавливает уникальный номер (id * -1).
Следующий код представляет собой пример приложения, которое имитирует поток - и дает сбой
private static void Main(string[] args)
{
ISessionFactory sessionFactory = CreateSessionFactory();
int userId = new Random().Next();
int basketId;
using (var session = sessionFactory.OpenSession())
{
using (var tx = session.BeginTransaction(IsolationLevel.ReadUncommitted))
{
var newBasket = new Basket {UserId = userId};
basketId = (int) session.Save(newBasket);
tx.Commit();
}
using (var tx = session.BeginTransaction(IsolationLevel.ReadUncommitted))
{
var basket = session.Get<Basket>(basketId);
basket.UserId = basket.Id*-1;
session.Save(basket);
// comment in this line to make it work:
//session.Flush();
var newBasket = new Basket {UserId = userId};
session.Save(newBasket);
tx.Commit();
}
}
}
Ошибка:
Необработанное исключение: NHibernate.Exceptions.GenericADOException: невозможно вставить: [ConsoleApplication1.Basket] [SQL: INSERT INTO [Basket] (UserId) VALUES (?); выберите SCOPE_IDENTITY ()] ---> System.Data.SqlClient.SqlException: Невозможно вставить повторяющуюся строку ключа в объект 'dbo.Basket' с уникальным индексом 'IX_Basket'.
Если я сбрасываю сессию (закомментированные строки), это работает, но зачем это нужно?
Я бы предпочел не сбрасывать мой сеанс и не позволять Commit () его обрабатывать.