Entity framework 在实体框架中以事务方式获取或创建DB对象

Entity framework 在实体框架中以事务方式获取或创建DB对象,entity-framework,transactions,entity-framework-4.1,transactionscope,Entity Framework,Transactions,Entity Framework 4.1,Transactionscope,我使用的是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); 通常这很好,

我使用的是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)时,其中一个测试始终失败,并出现“序列包含多个元素”。当我自己运行这个测试时,它运行得很好

问题似乎很明显:多个线程同时调用上述代码,每个线程创建一个新的用户行。但解决办法是什么

当然,正确的解决方案是一个事务,但我就是无法让它工作。如果我启动一个DbTransaction,EF将不会使用正常的DbTransaction。如果我使用TransactionScope,它要么没有效果(发生相同的错误),要么EF尝试并未能启动分布式事务,即使我遵循


这真的很令人沮丧,因为用普通的老SQL做这样一件小事:开始事务、选择、插入、提交事务。我怎样才能让它在EF中工作?它不一定要使用事务——不管是什么使它工作。

如果数据库对
Sid
唯一的
约束,则第一条语句(唯一可能导致您描述的错误的语句)永远不会失败。是吗?应该这样。这是确保
sid
真正具有全局唯一性的唯一方法

啊,那是另一整罐虫子。我想要一个唯一的约束,但是当实体框架从模型中创建DB时,如何让它创建一个约束呢?即使我有一个,但是,它不会解决根本的问题-它只会被更早地发现。是的,这就解决了问题。事实上,这是解决这个问题的唯一办法。即使在纯SQL中,也可能与未提交的数据发生冲突<代码>唯一
约束可解决此问题。你只需要在错误发生时处理它。另外一件事:谢谢,我添加了这里描述的唯一约束-它比这个失败的测试有更大的用途,所以它非常方便。顺便说一句。即使使用普通SQL,事务本身也不能确保记录是唯一的。您必须在
选择中使用锁定表提示来确保。EF不支持表格提示。你是对的,我没想到。看起来是一个独特的约束,捕捉错误是唯一的方法。