Je reçois le message d'erreur indiqué dans le titre d'une requête LINQ comprenant 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
et db2
sont des contextes associés à deux fichiers edmx différents. Comment puis-je surmonter cette erreur?
Vous devrez effectuer deux requêtes sur la 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 };
Le .ToArray()
est crucial. Cela empêche EF d'essayer d'exécuter la requête combinée (ce qui échouera car il utilise deux contextes différents). Vous pouvez utiliser .AsEnumerable()
si vous préférez garder le chargement paresseux.
Et votre question de suivi:
Existe-t-il un autre moyen d'optimiser la requête LINQ? C'est, effectuer l'action dans une seule requête LINQ elle-même?
Pour que votre requête d'origine 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 signifie une seule chaîne de connexion. Vous pouvez y parvenir de plusieurs manières:
Vous devez soit ajouter la deuxième table au modèle du premier contexte. S'il s'agit de plusieurs bases de données, vous devez effectuer la recherche secondaire côté client à l'aide d'une jointure Linq to Objects.
Vous devez créer manuellement EntityConnection, qui contient des ressources provenant de tous les .EDMX que vous souhaitez utiliser.
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="MyConnectionString""
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
}
}