linq to entities - Implementing if-not-exists-insert using Entity Framework without race conditions -
using linq-to-entities 4.0, there correct pattern or construct safely implementing "if not exists insert"?
for example, have table tracks "user favorites" - users can add or remove articles list of favorites.
the underlying table not true many-to-many relationship, instead tracks additional information such date favorite added.
create table userfavorite ( favoriteid int not null identity(1,1) primary key, userid int not null, articleid int not null ); create unique index ix_userfavorite_1 on userfavorite (userid, articleid);
inserting 2 favorites same user/article pair results in duplicate key error, desired.
i've implemented "if not exists insert" logic in data layer using c#:
if (!entities.favoritearticles.any( f => f.userid == userid && f.articleid == articleid)) { favoritearticle favorite = new favoritearticle(); favorite.userid = userid; favorite.articleid = articleid; favorite.dateadded = datetime.now; entities.addtofavoritearticles(favorite); entities.savechanges(); }
the problem implementation it's susceptible race conditions. example, if user double-clicks "add favorites" link 2 requests sent server. first request succeeds, while second request (the 1 user sees) fails updateexception wrapping sqlexception duplicate key error.
with t-sql stored procedures can use transactions lock hints ensure race condition never occurs. there clean method avoiding race condition in entity framework without resorting stored procedures or blindly swallowing exceptions?
you try wrap in transaction combined 'famous' try/catch pattern:
using (var scope = new transactionscope()) try { //...do thing... scope.complete(); } catch (updateexception ex) { // here second request ends up... }
Comments
Post a Comment