65 votes

Erreur : "L'expression LINQ spécifiée contient des références à des requêtes qui sont associées à des contextes différents"

Je reçois l'erreur indiquée dans le titre à partir d'une requête LINQ qui inclut deux tables provenant de deux fichiers edmx différents. Voici la requête :

var query = (from a in db1.Table1
           join b in db1.Table2 on a.Id equals b.Id
           orderby a.Status
           where b.Id == 1 && a.Status == "new"
           select new
           {
               Id = a.Id,
               CompanyId = (from c in db2.Company
                            where s.Id == a.Id
                            select
                            new { c.CompanyId })
           });

db1 y db2 sont des contextes qui sont associés à deux fichiers edmx différents. Comment puis-je surmonter cette erreur ?

131voto

Allon Guralnek Points 8545

Vous devrez effectuer deux requêtes de base de données :

var IDs =  (from a in db1.Table1 
            join b in db1.Table2 on a.Id equals b.Id 
            orderby a.Status 
            where b.Id == 1 && a.Status == "new" 
            select new a.Id).ToArray();

var query = from c in db2.Company
            join a in IDs on c.Id equals a.Id
            select new { Id = a.Id, CompanyId = c.CompanyId };

El .ToArray() est crucial. Il empêche EF d'essayer d'exécuter la requête combinée (qui échouera puisqu'elle utilise deux contextes différents). Vous pouvez utiliser .AsEnumerable() si vous préférez continuer à charger paresseusement.


Et votre question de suivi :

Existe-t-il un autre moyen de rendre la requête LINQ plus optimisée ? C'est-à-dire d'effectuer l'action dans une seule requête LINQ elle-même ?

Pour que votre requête originale puisse être exécutée avec succès, elle ne doit utiliser qu'un seul contexte de données, ce qui signifie que toutes les données doivent être disponibles à partir d'un seul EDMX, ce qui implique une seule chaîne de connexion. Il existe plusieurs façons d'y parvenir :

  • Si les deux tables sont sur la même base de données, ajoutez-les toutes les deux à un seul EDMX.
  • Si elles se trouvent sur des bases de données différentes mais sur la même instance, créez une vue sur l'une des bases de données qui sélectionne la table sur l'autre base de données, puis ajoutez la table locale et la vue à un seul EDMX.
  • S'ils sont sur des instances/serveurs différents, créez un serveur lié, puis créez une vue de la table sur le serveur lié, puis ajoutez la table et la vue locales à un seul EDMX.

2voto

Jim Wooley Points 6323

Vous devez soit ajouter la seconde table au modèle du premier contexte. Si le contexte se trouve dans plusieurs bases de données, vous devez effectuer la recherche secondaire côté client en utilisant une jointure Linq to Objects.

0voto

Vous devez créer manuellement EntityConnection avec les ressources de tous les .EDMX que vous voulez utiliser. Vous pouvez le faire soit en ajoutant la connexion à app.config, soit par programme. Ensuite, vous pouvez créer le DBContext en utilisant l'EntityConnection préparée.

méthode a)

<add name="MyConnection"
connectionString="metadata=res://*/Entities.ModuleA.csdl|res://*/Entities.ModuleA.ssdl|res://*/Entities.ModuleA.msl|res://*/Entities.ModuleB.csdl|res://*/Entities.ModuleB.ssdl|res://*/Entities.ModuleB.msl;
provider=System.Data.SqlClient;provider connection string=&quot;MyConnectionString&quot;"
providerName="System.Data.EntityClient" />

using (EntityConnection oEntityConnection =
    new EntityConnection("name=MyConnection"))
{
    using(DbContext oDBContext = new DbContext(oEntityConnection))
    {
        //your code - available are entities declared in Entities.ModuleA and Entities.ModuleB
    }
}

méthode b)

 using (EntityConnection oEntityConnection =
        new EntityConnection(new MetadataWorkspace(
        new string [] { 
"res://Entities.ModuleA/", 
"res://Entities.ModuleB/" 
},
        new Assembly[] { 
Assembly.GetAssembly(typeof(Entities.ModuleA.AnyType)),
Assembly.GetAssembly(typeof(Entities.ModuleB.AnyType)) 
}
        )))
    {
        using(DbContext oDBContext = new DbContext(oEntityConnection))
        {
            //your code - available are entities declared in Entities.ModuleA and Entities.ModuleB
        }
    }

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