2010-03-18 6 views
6

J'ai une seule table dans une base de données appelée utilisateursLINQ to SQL exception de contrainte ignorent unique et continuer

 
Users 
------ 
ID (PK, Identity) 
Username (Unique Index) 

j'ai installé un index unique sur la table pour éviter les doublons Nom d'utilisateur. J'énumère alors à travers une collection et crée un nouvel utilisateur dans la base de données pour chaque article. Ce que je veux faire est juste d'insérer un nouvel utilisateur et ignorer l'exception si la contrainte de clé unique est violée (comme c'est clairement un enregistrement en double dans ce cas). Ceci est pour éviter d'avoir à créer où n'existe pas type de requêtes. Tout d'abord, cela va-t-il être plus efficace ou est-ce que mon code d'insertion doit plutôt vérifier les doublons? Je suis attiré plus vers la base de données ayant cette logique car cela empêche tout autre type de client d'insérer des données en double.

Mon autre problème concerne LINQ To SQL. J'ai le code suivant:

public class TestRepo 
{ 
    DatabaseDataContext database = new DatabaseDataContext(); 

    public void Add(string username) 
    { 
     database.Users.InsertOnSubmit(new User() { Username = username }); 
    } 

    public void Save() 
    { 
     database.SubmitChanges(); 
    } 
} 

Et puis j'itérer sur une collection et insérer de nouveaux utilisateurs, sans tenir compte des exceptions:

TestRepo repo = new TestRepo(); 

foreach (var name in new string[] { "Tim", "Bob", "John" }) 
{ 
    try 
    { 
     repo.Add(name); 
     repo.Save(); 
    } 
    catch { } 
} 

La première fois est exécuté, grand, j'ai trois utilisateurs dans le table. Si je supprime le second et réexécute ce code, rien n'est inséré. Je m'attendais à ce que la première insertion échoue avec l'exception, la seconde à réussir (comme je viens de retirer cet élément de la base de données) et la troisième à échouer. Ce qui semble se produire est qu'une fois que SqlException est levée (même si la boucle continue à itérer) toutes les insertions suivantes échouent - même quand il n'y a pas une ligne dans la table qui causerait une violation unique.

Quelqu'un peut-il expliquer cela?

P.S. La seule solution de contournement que j'ai pu trouver était d'instancier le repo chaque fois avant l'insertion, alors cela a fonctionné exactement comme excepté - indiquant que c'est quelque chose à voir avec le DataContext LINQ To SQL.

Merci.

+0

J'ai mal lu votre code en écrivant mon post précédent, donc ma réponse était tout à fait faux, c'est pourquoi je l'ai supprimé. –

Répondre

0

Essayez d'appeler le DataContext.Refresh sur votre DataContext entre deux tests.

Je pense que vous êtes bloqué sur la mise en cache interne dans Linq-to-Sql, c'est pourquoi recréer le DataContext agit comme une solution, lorsque vous créez un DataContext, le cache du nouvel objet sera vide .

0

Vous devriez vérifier la présence en utilisant le try try trick est mauvais.

foreach (var name in new string[] { "Tim", "Bob", "John" }) 
{ 
    var u = from users in db.Users 
      where users.username == name 
      select users; 

    if (u.Count() == 0) 
    { 
     User user = new User(); 
     user.name = name; 
     db.Users.InsertOnSubmit(user); 
     db.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict); 
    } 
} 
+1

Ce n'est pas un accès concurrentiel. – Simon

1

Sur la deuxième datacontext d'insertion va essayer à nouveau d'insérer des objets premiers car il est assis sur la carte d'identité pour cette DataContext (votre souhait d'insérer « Tim » est toujours en attente - après la première capture).

Dans la première boucle, vous insérez « Tim » En deuxième « Tim » et « Bob » En troisième « Tim », « Bob » et « John » Donc, vous n'insérez seulement « Bob » dans la deuxième boucle et c'est pourquoi échoue.

Vous pouvez essayer de supprimer le nom défaillant de DataContext dans la mémoire cache, mais de toute façon, plusieurs soumissions dans un contexte de données sont une très mauvaise idée (j'ai été brûlé dessus).

0

Il est difficile de dire si votre méthode est "plus efficace". Cela dépend de la fréquence à laquelle vous obtenez des comptes en double. Si vous avez un taux très élevé, vous perdez de la vitesse, car il faudra probablement plus de temps pour traiter l'exception que pour vérifier l'existence de l'enregistrement.

Si vous souhaitez optimiser votre vitesse, créez une procédure stockée à vérifier et à insérer si elle ne se trouve pas dans la base de données.