EntityFramework, Insérez s'il n'existe pas, sinon la mise à jour
Je vais avoir un Jeu d'entités de Pays, reflétant une table de base de données '<'char(2) char(3),nvarchar(50> dans ma base de données.
Im ayant un analyseur qui renvoie un Pays[] tableau de analysée pays, et d'avoir des problèmes de mise à jour dans le droit chemin. Ce que je veux, c'est: Prendre l'éventail de pays, pour ces pays de ne pas déjà dans la base de données insérer, et ceux existants mise à jour si tous les champs sont différents. Comment cela peut-il être fait?
void Method(object sender, DocumentLoadedEvent e)
{
var data = e.ParsedData as Country[];
using(var db = new DataContractEntities)
{
//Code missing
}
}
Je pensais à quelque chose comme
for(var c in data.Except(db.Countries)) but it wount work as it compares on wronge fields.
L'espoir que quelqu'un a eu ce problème avant et que vous avez une solution pour moi. Si je ne peux pas utiliser le Pays de l'objet et de l'insérer/mettre à jour un tableau facile, je ne vois pas beaucoup benefict de l'utilisation du cadre, comme des artistes je pense que c'est plus rapide à écrire un custom script sql qui les insère à la place de l'ect vérifier si un pays est déjà dans la base de données avant de les insérer?
Solution
Voir la réponse de la poste à la place.
J'ai ajouté remplacer égal à mon pays la classe:
public partial class Country
{
public override bool Equals(object obj)
{
if (obj is Country)
{
var country = obj as Country;
return this.CountryTreeLetter.Equals(country.CountryTreeLetter);
}
return false;
}
public override int GetHashCode()
{
int hash = 13;
hash = hash * 7 + (int)CountryTreeLetter[0];
hash = hash * 7 + (int)CountryTreeLetter[1];
hash = hash * 7 + (int)CountryTreeLetter[2];
return hash;
}
}
et puis n':
var data = e.ParsedData as Country[];
using (var db = new entities())
{
foreach (var item in data.Except(db.Countries))
{
db.AddToCountries(item);
}
db.SaveChanges();
}
- Aussi, vous pouvez utiliser nouvellement libérés de la bibliothèque qui sera automatiquement réglée à l'etat de toutes les entités de l'entité graphique. Vous pouvez la lire ma réponse à la question similaire.
Vous devez vous connecter pour publier un commentaire.
Je voudrais faire simple:
Je ne sais pas combien de fois votre application doit s'exécuter ou de nombreux pays de votre monde est. Mais j'ai le sentiment que ce n'est rien où vous devez penser sophistiqué de l'optimisation des performances.
Modifier
Approche Alternative qui ne délivrera qu'une seule requête:
SingleOrDefault
est appelé. La solution de @Miroprocessor est très bien, il serait frappé de la DB qu'une seule fois (lors de laToList
est appelé). Cependant, il serait potentiellement de la charge de trop nombreux pays, vous n'avez pas besoin. Par exemple: Si votredata
collection ne contient que peu (disons 2) les pays et dans la DB sont déjà de 200 pays,ToList
serait de charger tous les 200 qui est un beaucoup de surcharge inutile. J'ai fourni une autre requête qui aurait frappé la DB qu'une seule fois, voir mon Edit.Except
extrait du premier tous pays de la DB et puis effectueExcept
dans la mémoire (j'ai juste testé). Il n'est pas surprenant parce que vous êtes à l'appel deExcept
surdata
qui est unIEnumerable
mais pas unIQueryable
. - Je trouver les Égaux/HashCode, à l'Exception méthode beaucoup trop lourd pour une telle tâche simple. Mais c'est peut être une question de goût.Except
procédure n'est pas mise à jour existante pays à tous. Il ignore simplement les pays et les feuilles de leurs valeurs comme ils sont dans la base de données.names.Contains(...)
est traduite dans unIN
clause SQL qui contient tous les noms de la liste en une seule requête.SaveChanges
appel est une transaction et, par conséquent, atomique. Je pense que la question est de savoir si le pays sont verrouillés lorsqu'ils sont lus, mais je ne sais pas la réponse à cette question.La forme moderne, l'utilisation plus tard EF versions serait:
AlreadyExists
peut venir de la vérification de la clé ou par l'interrogation de la base de données pour voir si l'élément existe déjà là.Vous pouvez implémenter votre propre
IEqualityComparer<Country>
et le passer à laExcept()
méthode. En supposant que votre Pays d'objet aId
etName
propriétés, un exemple de cette mise en œuvre pourrait ressembler à ceci:et l'utiliser comme
Bien que, dans votre cas, il semble que vous suffit d'extraire de nouveaux objets, vous pouvez utiliser
var newCountries = data.Where(c => c.Id == Guid.Empty);
si votre Id est Guid.La meilleure façon est d'inspecter la
Country.EntityState
de la propriété et de prendre des mesures à partir de là sur la valeur (Détaché, Modifié, Ajouté, etc.)Vous avez besoin de fournir plus d'informations sur ce que votre
data
collection comporte, c'est à dire sont le Pays des objets récupérés à partir d'une base de données par le biais de la entityframework, auquel cas leur contexte peuvent être suivis, ou êtes-vous de les générer à l'aide d'une autre façon.Je ne suis pas sûr que ce sera la meilleure solution, mais je pense que vous devez obtenir tous les pays de DB puis vérifier avec votre analysé les données