Connexion LINQ utilisant IEnumerable
collection constante
Lors de l'utilisation d'une clause LINQ JOIN dans une instruction SELECT d'une autre instruction JOIN, l'erreur "Impossible de créer une valeur constante de type API.Models.PersonProtocol. Seuls les types primitifs ou énumérés sont pris en charge dans ce contexte" se produit. Cette erreur se produit car la IEnumerable
CollectionppCombined
ne peut pas être utilisée comme valeur constante dans un contexte de base de données.
Dans le code fourni :
<code class="language-csharp">var persons = db.Favorites .Where(x => x.userId == userId) .Join(db.Person, x => x.personId, y => y.personId, (x, y) => new PersonDTO { personId = y.personId, addressId = y.addressId, favoriteId = x.favoriteId, personProtocol = (ICollection<PersonProtocol>) ppCombined .Where(a => a.personId == x.personId) .Select( b => new PersonProtocol() { personProtocolId = b.personProtocolId, activateDt = b.activateDt, personId = b.personId }) });</code>
Ce code tente de concaténer les données des tables db.Favorites
et db.Person
, puis projette le résultat dans un objet PersonDTO
. Dans l'objet PersonDTO
, il existe une propriété personProtocol
définie sur le résultat d'une requête LINQ sur la collection ppCombined
.
Le problème est d'essayer d'utiliser ppCombined
comme valeur constante dans un contexte de base de données. ppCombined
est un objet IEnumerable
construit en mémoire, pas une table de base de données. Lors de l'exécution d'une requête LINQ, il tente de convertir la projection personProtocol
en une instruction SQL. Cependant, il ne peut pas le faire car ppCombined
n'est pas une table de base de données ou un type primitif.
Solution
Pour résoudre cette erreur, nous pouvons récupérer les éléments filtrés dans ppCombined
en mémoire après avoir récupéré d'autres attributs de la base de données. Voici le code modifié :
<code class="language-csharp">var persons = db.Favorites .Where(f => f.userId == userId) .Join(db.Person, f => f.personId, p => p.personId, (f, p) => new // 匿名对象 { personId = p.personId, addressId = p.addressId, favoriteId = f.favoriteId, }) .AsEnumerable() // 数据库查询在此结束,其余部分是在内存中进行的查询 .Select(x => new PersonDTO { personId = x.personId, addressId = x.addressId, favoriteId = x.favoriteId, personProtocol = ppCombined .Where(p => p.personId == x.personId) .Select(p => new PersonProtocol { personProtocolId = p.personProtocolId, activateDt = p.activateDt, personId = p.personId }) .ToList() });</code>
Dans ce code modifié, la requête de base de données se termine par la méthode AsEnumerable()
. Cela signifie que le reste de l'opération est effectué entièrement en mémoire. Ensuite, dans une projection Select
basée sur la mémoire de l'objet anonyme, filtrez la collection ppCombined
et convertissez-la en liste.
En séparant la requête de base de données du traitement en mémoire, nous évitons le problème du passage des collections en mémoire dans le contexte de la base de données, résolvant ainsi le bug.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!