L'exécution d'Insertion OU de mise à Jour (upsert) sur sql server compact edition
J'ai le c# projet qui est à l'aide de sql server compact edition et entity framework pour l'accès aux données. J'ai le besoin d'insérer ou de mettre à jour une grande quantité de lignes, 5000+ ou plus à la db, donc si la clé existe mise à jour de l'enregistrement en cas de ne pas l'insérer. Je ne peux pas trouver un moyen de le faire avec compact edition et EF avec des performances horribles, c'est à dire de prendre 2 minutes de plus sur un core i7 ordinateur. J'ai essayé de chercher le dossier pour voir s'il existe ensuite d'insérer si pas ou mettre à jour si elle le fait, la recherche est le tueur sur que. J'ai essayé de compiler la requête de recherche et qui ne lui a donné qu'une petite amélioration. Une autre chose que j'ai essayé est de l'insertion de l'enregistrement dans un try catch et en cas d'échec de mise à jour, mais qui m'oblige à savechanges sur chaque dossier pour obtenir l'exception plutôt que à la fin qui est une performance killer. Évidemment, je ne peux pas utiliser des procédures stockées, car il est compact edition. Aussi j'ai regardé seulement l'exécution de t-sql directement en quelque sorte sur la db, mais l'absence de traiter les déclarations compact semble écarter cette possibilité.
J'ai cherché dans le monde entier et d'idées. Je voulais vraiment utiliser compact si je peux m'exprimer plus pour le déploiement des avantages et la capacité d'empêcher l'utilisateur de creuser autour de la db. Tout suggesitons serait appréciée.
Grâce
- Merci pour les suggestions. Je vais passer un peu de temps demain des tests de performance de ces idées. J'ai essayé plusieurs façons aujourd'hui avec sql express et rapide comme l'éclair, sans même l'aide de procédures stockées. À l'aide de ses procédures stockées et de la nouvelle instruction merge est presque instantanée.
Vous devez vous connecter pour publier un commentaire.
Vous pourriez peut-être obtenir le résultat que vous cherchez en utilisant des requêtes simples.
Disons que le la table que vous souhaitez insérer ou de mettre à jour, c'est comme cela
d'abord, vous pouvez créer une table temporaire avec les nouvelles valeurs (vous pouvez utiliser un SELECT INTO ou d'autres moyens de la créer)
maintenant, vous devez faire deux choses, la mise à jour des lignes dans l'original, puis insérez les nouvelles valeurs
Lorsque nous sommes à l'aide de SQL CE (et SQL 2005 Express que ce soit), nous appelons toujours une mise à jour d'abord et ensuite appeler un insert si la udate donne un nombre de lignes de 0. C'est très simple à mettre en œuvre et ne nécessite pas de expensice try..catch pour le contrôle de flux.
INSERT
si le nombre de lignes est 0 lorsque CE n'est pas en chargeIF
?UPDATE
SQL séparément et utiliser le résultat deExecuteNonQuery
dans .NET pour décider si nous devons appelerINSERT
.Donné votre énoncé du problème, je vais deviner que ce logiciel n'assume relativement costaud de l'environnement. Avez-vous envisagé de prendre la tâche de déterminer hors de sqlce et de le faire sur votre propre? Essentiellement, prenez une liste triée de tous les Id(clés?) à partir de la table correspondante et la vérification de tous les objets qui touche à l'encontre de la liste avant de la queue pour l'insertion?
Cela fait quelques hypothèses qui serait de mauvaises nouvelles avec une DB typique, mais que vous pouvez probablement vous en sortir avec dans sqlce. E. g., il suppose que les lignes ne seront pas insérées ou modifiées de manière significative par un autre utilisateur lorsque vous effectuez cette insertion.
Si la liste des touches est trop longue pour être raisonnablement tenir en mémoire pour un tel contrôle, j'ai peur, je dirais que sqlce juste peut-être pas le bon outil pour le travail. 🙁
Je ne sais pas si c'est faisable ou pas, comme je n'ai pas utilisé le Cadre de l'Entité, mais avez-vous essayé de lancer la mise à jour de la première et de la vérification de la rowcount -- insertion si aucune ligne n'ont été mis à jour? Cela peut être plus rapide que d'intercepter les exceptions. C'est généralement une mauvaise pratique d'utiliser les exceptions pour le contrôle de flux, et souvent ralentit les choses de façon spectaculaire.
Si vous pouvez écrire du SQL directement, alors le moyen le plus rapide de le faire serait d'obtenir toutes les données dans une table temporaire, et ensuite mettre à jour ce qui existe et insérez le repose (comme dans Andrea Bertani l'exemple ci-dessus). Vous devriez obtenir des résultats légèrement meilleurs en utilisant une jointure gauche sur la table d'origine dans le sélectionner dans votre insert, et à l'exclusion de toute les lignes avec des valeurs de la table d'origine qui ne sont pas nulles:
Je vous conseille d'utiliser SqlCeResultSet directement. Vous perdez la nice de type solidité de l'EF, mais la performance est incroyablement rapide. Nous sommes passés d'ADO.NET 2.0-style TypeDataSets à SqlCeResultSet et SqlCeDataReader et vu 20 à 50 fois les augmentations de vitesse.
Voir SqlCeResultSet. Pour un .NETCF projet, je l'ai enlevé presque tout le code sql en faveur de cette classe.
Il suffit de chercher "SqlCeResultSet" ici et msdn.
Un aperçu rapide:
Ouvrir le jeu de résultats.
Si vous avez besoin de chercher (pour vérifier l'existence), vous devrez fournir un indice pour le jeu de résultats.
Chercher sur le jeu de résultats & lire pour vérifier si vous avez trouvé la ligne. Ce qui est extrêmement rapide, même sur des tables avec des dizaines de milliers de lignes (parce que la recherche utilise l'index).
D'insérer ou de mettre à jour l'enregistrement (voir SqlCeResultSet.NewRecord).
Nous avons réussi à développer un projet avec un sqlce base de données avec un produit principal de la table avec plus de 65 000 lignes (lecture/écriture avec 4 index).
SQL Server compact edition est assez tôt dans le développement à ce point. Aussi, en fonction de votre appareil, la mémoire-l'accès au disque peut être assez lente, et SQLCE plus .Type de NET-marge de sécurité est assez intensif. Il fonctionne mieux avec un joli statique de la banque de données.
Je vous suggère d'utiliser un briquet-poids de l'API ou de considérer SQLite.