Reputation: 3343
Here's a scenario: There are users, users have skills. If a user specifies new skill, it needs to be added, however if user specifies existing skill - it should link to the existing one. So, setup is pretty basic - 3 tables (users, skills, userSkillsLink). It's a web app, but I don't want to add every skills there's in a drop down - so I won't know if skill exists right away. I could check if skill already exists using select, but in web app that's not the best choice - not thread safe. I can keep a track of which skills already exist in a separate cache, but this problem should be.. very common, so I'm thinking maybe I'm over-complicating, and there's a known solution already.
Thanks !
Upvotes: 2
Views: 759
Reputation: 59101
I think the proper way to solve this with transactional semantics is:
Then you handle concurrency by letting the transaction throw an exception. In your exception handler you can re-query and use the existing value.
If your transaction dies again (if the record gets deleted), just give an appropriate error message to the user, and tell them to try again.
You can't really do this any other way, since you can't query and commit atomically besides just wrapping it in a transaction, even in a stored procedure.
Upvotes: 1
Reputation: 80714
I would create a stored procedure that would take name of the skill as argument, perform the check and insert new record if needed, then return the resulting record (either existing or new).
Then I can map that procedure to a method on DbContext
and make that method return an entity.
Then I can just call it: var skill = database.GetSkillCreateIfNone( skillName )
Upvotes: 2