web-dev-qa-db-fra.com

Jointure de tables de deux bases de données à l'aide de la structure d'entité

Je travaille sur une application Web ASP.NET MVC 4. J'utilise Entity Framework en tant que couche d'accès aux données, en utilisant la première approche de la base de données (fichier .edmx).

Actuellement, j'ai un problème avec les tables de jointure définies dans deux bases de données différentes (c'est-à-dire que j'ai deux fichiers .edmx).

Par exemple, si je veux joindre des tables, j'exécute la requête suivante: -

public ActionResult AutoComplete(string term)
{
   var tech = repository.AllFindTechnolog(term).Take(100);//Call to the first database
   var resources = repository.GetResources(tech.Select(a => a.IT360ID.Value).ToArray(), false);//call to the second database

   var query = from techItems in tech
         join resourcesItems in resources
         on techItems.IT360ID.Value equals resourcesItems.RESOURCEID // join based on db2ID
         orderby techItems.PartialTag
         select new //code goes here

   return Json(query, JsonRequestBehavior.AllowGet);
}

J'aurai deux appels distincts à la base de données et une jointure à l'intérieur du serveur d'applications, ce qui n'est pas la meilleure solution orientée performances. Idéalement, les jointures se dérouleront complètement à l'intérieur du moteur de base de données.

Je sais qu'une procédure stockée me permettra de joindre des tables de différentes bases de données uniquement sur le serveur, mais je ne souhaite pas utiliser SP car cela rendrait mon code moins maintenable et moins testable. 

Donc, je cherche une solution où je peux faire la jointure en utilisant la structure d'entité et aboutir à une jointure de base de données unique?

11
john Gu

Si vous souhaitez le faire avec un seul appel de base de données, vous devez créer une vue dans la base de données qui joint les 2 tables à partir de bases de données distinctes. Une fois que la vue est créée, vous pouvez l'ajouter à EF sous la forme d'un objet unique, que vous pouvez manipuler plus avant et hors de la requête. La vue sera essentiellement une table et il sera facile à maintenir et à relier à un modèle fortement typé.

Une autre façon, similaire à celle que vous avez publiée, est d’interroger des fichiers .edmx distincts, puis de les joindre. Oui, il y a 2 appels à la base de données, mais cela ne devrait pas être si cher et ne remarquera probablement pas de différence .

using(var db = new MyEntities())
using (var db2 = new MyEntities2())
{
   var one = db.Table1.AsEnumerable();
   var two = db2.Table2.AsEnumerable(); 

   var result = from o in one
                join t in two on o.Id equals t.Id
                // blah blah

}
4
CSharper

La réponse de @ CSharper est proche. Comme @Oliver l'a mentionné dans les commentaires, IEnumerable charge la table dans la mémoire de l'application, ce qui entraîne des plantages si la base de données est volumineuse. 

La solution consiste à utiliser IQueryable, qui peut être appelé avec LINQ - ceci produit un code SQL beaucoup plus rapide. 

// This is a generic method, modify to your needs
public ActionResult Details(int? id)
   var one = db.Table1.AsQueryable();
   var two = db2.Table2.AsQueryable(); 

   // since you're using MVC EF, I assume you want to put this in a viewmodel 
   // (in this case ObjectCombined)
   // assume "id" is passed as parameter 
   Object1 result1 = (from o in one where one.id == id select o).Single();
   Object2 result2 = (from t in two where t.id == o.id select t).Single();
   ObjectCombined result = new ObjectCombined(result1, result2);
   return View(result);
}
2
chakeda

vous pouvez créer une vue ou une procédure stockée, votre instruction sql peut alors créer une requête cross-db, assurez-vous simplement que vos informations d'identification peuvent DML ou DDL sur les deux bases. sinon, essayez les entités imbriquées qui vous éviteront le bogue linq si vous ne déclarez pas l'entité db dans une instruction using.

0
CyberNinja

Puis-je vous suggérer d’utiliser un synonyme dans votre base de données. Par exemple, vous pouvez créer un synonyme pour la table de ressources de la base de données contenant votre table technique. Cela vous évitera d'avoir à gérer 2 fichiers EDMX. Au lieu de cela, vous pouvez avoir un seul fichier EDMX et vous pouvez simplement joindre votre table technique au synonyme de la table de ressources et le tour est joué - vous êtes sur votre chemin.

UPDATE: Veuillez noter que si vous utilisez des synonymes, vous devrez effectuer un peu plus de travail dans le fichier EDMX pour le faire fonctionner dans Entity Framework. Voici un article blog qui a été publié par un programmeur qui l’a fait fonctionner. Voici l'original stackoverflow question qu'elle a posée.

HAPPY CODING !!! :)

0
Gjohn