Транзакционно получить или создать объект БД в Entity Framework - PullRequest
2 голосов
/ 09 августа 2011

Я использую Entity Framework 4.1 и у меня, казалось бы, простое требование: я хочу либо получить объект по уникальному ключу, либо, если он еще не существует, создать его:

        var user = db.Users.SingleOrDefault(u => u.Sid == sid);
        if (user != null)
            return user;

        user = new User(sid);
        db.Users.Add(user);

Обычно это работает нормально, но когда я запускаю кучу тестов вместе (используя MSTest), один из них постоянно завершается с ошибкой «Последовательность содержит более одного элемента». Когда я запускаю этот тест, он работает нормально.

Проблема кажется очевидной: несколько потоков вызывают вышеуказанный код одновременно, и каждый создает новую строку пользователя. Но каково решение?

Конечно, правильное решение - это транзакция, но я просто не могу заставить ее работать. EF не будет использовать обычную транзакцию DbTransaction, если я ее начну. Если я использую TransactionScope, он либо не действует (возникает та же ошибка), либо EF пытается и не может запустить распределенную транзакцию, даже если я следую совету об открытии соединения сначала .

Это действительно расстраивает, потому что с простым старым SQL делать такую ​​тривиальную вещь: начать транзакцию, SELECT, INSERT, зафиксировать транзакцию. Как я могу заставить это работать в EF? Он не должен использовать транзакции - все, что заставляет его работать.

1 Ответ

2 голосов
/ 09 августа 2011

Первый оператор (единственный, который может вызвать описанную вами ошибку) никогда не потерпит неудачу, если ваша БД имеет ограничение UNIQUE на Sid. Является ли? Должно. Это единственный способ убедиться, что sid действительно уникален во всем мире.

...