1

Consider the following simple User table

enter image description here

I want to write Linq To SQL Code that returns a user by some predicate, e.g. the email address, or creates the user if he does not yet exists. The code might look like

User GetUser(String name, String email) {
    using (var context = new DataContext()) {
        User user = context.Users.FirstOrDefault(u => u.email.Equals(email));
        if (user != null)
            return user;
        user = new User() { name = name, email = email };
        context.Users.InsertOnSubmit(user);
        context.SubmitChanges();
        return user;
    }
}

The code might get executed in parallel, but should not create duplicate users.

I would prefer to not create a unique constraint for the table for several reasons. Do you see any alternative that could be realized using Linq To SQL and without touching the database?

1
  • ur code is n't it already checking is there any duplicate or not? Commented Sep 1, 2014 at 10:47

1 Answer 1

4

Use TransactionScope (Serializable isolation level is by default):

User GetUser(String name, String email) 
{
    using (var tran = new TransactionScope())
    {
        using (var context = new DataContext()) 
        {
            User user = context.Users.FirstOrDefault(u => u.email.Equals(email));
            if (user != null)
                return user;
            user = new User() { name = name, email = email };
            context.Users.InsertOnSubmit(user);
            context.SubmitChanges();

            tran.Complete();

            return user;
        }
    }
}

More info on Transactions support in LINQ to Sql: http://msdn.microsoft.com/en-us/library/bb386995

Sign up to request clarification or add additional context in comments.

4 Comments

Instead of creating a duplicate this will deadlock. But at least it is safe and it is as good as it can get with L2S.
usr - could you describe an example of deadlock for OP in this case?
Yes, the case of a conflict. Both transactions read and S-lock, then both transactions try to write and X-lock. Classic deadlock. This is exactly the case where without SERIALIZABLE a duplicate row would have been inserted.
I upvoted this. This is a sane solution. It would benefit from a retry loop, though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.