Comment gérer les problèmes de parallélisme SQL dans un site Web

Je fais un site web en utilisant asp.net mvc. J'ai une table qui ressemble à ceci

Create Table Items( [Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY, [Colname] [nvarchar](20) NOT NULL //OTHER UNIMPORTANT COLS HERE ) ALTER TABLE Items ADD CONSTRAINT UN_Colanme UNIQUE(Colname) 

À partir de mon site Web, j'essaie souvent de créer de nouveaux éléments ou de sélectionner des éléments dans la database (à l'aide du entity framework). Voici comment ça se passe dans c #

 var item = db.Items.FirstOrDefault(i => i.Colname == "foo"); if(item == null) { item = new Item("foo"); db.Items.Add(item); } //some stuff with item db.SaveChanges(); 

Parfois, deux requests arrivent en même time, essayant toutes deux de créer un object avec le même nom de col. Alors que la contrainte unique empêche la database de stocker des valeurs incorrectes, essayer d'save les modifications triggers une exception car la contrainte est violée.

Est-ce que attraper cette exception est la façon normale de gérer cela? Pourrais-je get de bonnes performances si, au lieu du code c # ci-dessus, j'ai créé une procédure stockée qui a verrouillé la table, puis inséré une nouvelle ligne uniquement si elle était autorisée, puis renvoyé cette ligne? Est-ce que c'est généralement fait?

Eh bien, il y a plusieurs façons de le faire. Je dirais que attraper l'exception est le less cher dans ce scénario. L'autre façon est d'élever le niveau d'isolation de la transaction à quelque chose de beaucoup plus élevé comme Serializable.

Dans ce scénario cependant, je voudrais juste attraper la violation de contrainte unique et continuer. Si nous y réfléchissions aussi en termes de programmation, nous pouvons penser à cette situation comme un double contrôle , en ce que nous vérifions, ce n'est pas là, puis entrer dans la transaction, voir c'est là, alors nous pouvons simplement jeter notre valeur et utiliser celui qui est là.

C'est pourquoi de nombreux développeurs utilisent des GUID ou des Ints alloués par DB comme key unique. Si votre key externe est légitimement allouée et est un doublon logique, utilisez la contrainte de duplication DB comme vous l'avez démontré ou envisagez d'utiliser un verrou pessimiste. Le server SQL dispose d'un outil que vous pouvez utiliser. Rechercher des exemples et des blogs

  • Utilisez la touche Guid
  • Utiliser DB alloué Int comme key
  • Utilisez la contrainte de colonne et interceptez l'exception (comme vous l'avez expliqué)
  • Utilisez un locking pessimiste, par exemple des fonctions embeddedes SQL

search Web pour "SQL Server sp_getapplock" sur la façon d'utiliser.