3 votes

Entity framework, lier automatiquement à l'entité existante lors de l'insertion

Je ne suis pas sûr que cela soit possible, mais j'insère beaucoup d'entités dans la base de données, et pour chaque élément, il a une propriété de langue qui est une entité. Actuellement, je crée un nouvel objet langue pour chaque élément qui est inséré, mais c'est juste pour les tests car cela crée beaucoup de doublons. Les langues devraient être uniques dans la base de données et devraient simplement pointer vers un enregistrement de langue existant, la seule façon que je peux imaginer est de faire des appels de service séparés pour chaque insertion afin de rechercher un code de langue et obtenir l'identifiant de la langue existante, ce qui génère beaucoup de surcharge.

Existe-t-il un moyen de rechercher automatiquement un enregistrement en fonction du code de langue et d'utiliser cet enregistrement ?

Merci

4voto

Slauma Points 76561

À la fois ObjectContext et DbContext ont des méthodes qui tentent de trouver une entité déjà chargée du contexte en mémoire - GetObjectByKey pour ObjectContext et Find pour DbContext. En utilisant ces méthodes, vous évitez de charger une entité Language plus d'une fois depuis la base de données.

Les deux méthodes ont besoin d'une valeur de clé primaire en tant que paramètre d'entrée pour rechercher l'entité par clé. Fondamentalement, pensez à ces méthodes comme accédant à un dictionnaire interne qui relie la clé primaire à l'objet entité.

Maintenant, en référence à votre commentaire...

Essentiellement en essayant de faire correspondre sur une valeur personnalisée plutôt que la valeur de l'id/clé primaire.

...vous ne pouvez pas utiliser ces méthodes car elles dépendent de la connaissance de la valeur de clé primaire que vous souhaitez rechercher.

Ce que je ferais serait de reproduire la logique du dictionnaire interne mentionné par votre propre dictionnaire qui relie votre "valeur personnalisée" à l'entité au lieu de la clé primaire. Je suppose que la valeur personnalisée est unique dans la table Language.

Ainsi, l'idée serait la suivante :

Étant donné que vous avez des entités comme ceci...

public class MyEntity
{
    public int Id { get; set; }
    public Language Language { get; set; }
    public string SomeOtherValue { get; set; }
    // ... more
}

public class Language
{
    public int Id { get; set; }             // valeur de clé primaire
    public string CustomValue { get; set; } // la valeur personnalisée unique
    // ... more
}

...et que vous avez une collection de données que vous utilisez pour insérer les nouvelles entités...

public class Data
{
    public string SomeOtherValue { get; set; }
    public string LanguageCustomValue { get; set; }
    // ... more
}

var dataList = new List
{
    new Data { SomeOtherValue = "A", LanguageCustomValue = "EN" },
    new Data { SomeOtherValue = "B", LanguageCustomValue = "FR" },
    new Data { SomeOtherValue = "C", LanguageCustomValue = "EN" },
    new Data { SomeOtherValue = "D", LanguageCustomValue = "EN" },
    // ... more
}

...alors vous pourriez utiliser ceci :

using (var context = new MyContext())
{
    var dict = new Dictionary();
    foreach (var data in dataList)
    {
        Language language;
        if (!dict.TryGetValue(data.LanguageCustomValue, out language))
        {
            // charger la langue une seule fois depuis la base de données
            language = context.Languages.SingleOrDefault(l =>
                l.CustomValue == data.LanguageCustomValue);
            dict.Add(data.LanguageCustomValue, language);
        }

        var myEntity = new MyEntity
        {
            SomeOtherValue = data.SomeOtherValue,
            Language = language
        };

        context.MyEntities.Add(myEntity);  // ou AddObject
    }
    context.SaveChanges();
}

Cela chargerait une seule entité Language par LanguageCustomValue, le ferait une seule fois et ne créerait pas de doublons d'objets Language dans la base de données.

1voto

user1695717 Points 31

Pas sûr exactement de ce que vous voulez dire ici, mais s'il s'agit d'une insertion, vous vérifieriez généralement si elle existe, et l'ajouteriez si ce n'est pas le cas. Vous pourriez stocker les langues en contexte si vous insérez un tas d'entités. Je ne suis pas sûr que ce soit la meilleure solution cependant. Je ne pense pas qu'il y ait un moyen rapide de trouver un objet dans le magasin ou le contexte sans clé. En fonction de la complexité de votre entité Language, vous pourriez caster la variable 'languages' du contexte ci-dessous ToDictionary() et parcourir cela à la place.

// 'db' est votre contexte ici.
var languages = db.Languages.all();
myentity MyEntity = new MyEntity();
myentity.property1 = "mynewvalue1";

var newlang = new Language{ LanguageName= "newlanguagename"};
// la langue existe ?
if (!languages.Any( u => u.LanguageName== newlang.LanguageName ))
 {

  // non :
  db.Languages.InsertOnSubmit(newlang);
  db.SubmitChanges();
  myentitly.Language = newlang;
 }
else{

  // oui :
  myentitly.Language = languages.Where( u => u.LanguageName== newlang.LanguageName).Single();
 }

db.MyEntities.InsertOnSubmit(myentity);
db.SubmitChanges();

1voto

Flater Points 6860

Étant donné que vous vous souciez des coûts de performance supplémentaires, je vous suggère ceci comme la manière la plus efficace de traiter cela :

Étape 1 : Assurez-vous que votre table des Langues est correcte.

Je ne suis pas sûr de la façon dont vous définissez quelles langues sont utilisées, donc je ne peux pas vous aider ici, assurez-vous simplement que votre table des langues contient toutes les lignes nécessaires. Supposons que votre table est comme suit :

{ Id: 1 ; Language: "Anglais" }
{ Id: 2 ; Language: "Français"  }
{ Id: 3 ; Language: "Allemand"  }

Étape 2 : Traitement de vos entités

Étape 2.1 : Créez un Dictionary pour mapper facilement votre table des Langues :

var lang_list = new Dictionary();

using(var db = new DbContext()
{
     foreach(var row in db.Languages.ToList())
     {
            lang_list.Add(row.Language, row.Id);
     }
}

//Désormais, vous pouvez vous référer à la liste locale.

Étape 2.2 : Ajout de la langue correcte à l'entité (à ajouter)

Je ne sais pas comment vous déterminerez quelle langue vous devez ajouter. Supposons que vous avez une variable de type string myLanguage qui contient le nom de la langue dont vous avez besoin.

Vous voudrez probablement utiliser quelque chose comme :

int foundvalue;

if(lang_list.TryGetValue( myLanguage , out foundvalue ))
{
     //si la langue se trouve dans la liste, la valeur (= l'id de la ligne dans la table des langues) sera stockée dans foundvalue
     myEntity.LanguageId = foundvalue;
}
else
{
     //si la langue n'a pas été trouvée dans la liste, définissez une langue par défaut (par exemple Anglais)
     myEntity.LanguageId = 1;
}

J'espère que cela vous aidera avec votre problème ?

Les avantages de l'utilisation de ce processus :

  • Vous n'avez à interroger la base de données qu'une seule fois pour les Langues. Une fois que la liste est remplie, elle sera stockée en mémoire, ce qui est une méthode meilleure en termes de performance.
  • Si une entité a une langue inattendue ou incorrecte définie, vous pourrez vous rabattre sur une langue par défaut.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X