Dépannage des jointures LINQ et des collections en mémoire
L'erreur "Impossible de créer une valeur constante de type... Seuls les types primitifs ou les types d'énumération sont pris en charge dans ce contexte" apparaît souvent lorsque l'on tente d'incorporer directement une collection en mémoire (comme ppCombined
dans cet exemple) dans une requête LINQ de base de données. En effet, les requêtes de base de données fonctionnent uniquement sur les données résidant dans la base de données ; la connexion avec des données en mémoire n'est pas directement prise en charge.
Le problème se manifeste généralement dans la clause Select
de la déclaration Join
. La tentative de création d'un objet PersonDTO
, y compris une propriété renseignée à partir de la collection en mémoire, provoque le conflit.
La cause profonde de l'échec de LINQ JOIN
L'erreur résulte de la tentative d'effectuer une opération de filtrage (clause Where
) sur la ppCombined
collection au sein de l'instruction Select
de la requête de base de données. Le moteur de base de données ne peut pas traduire cette opération en mémoire en son propre équivalent.
Solution : Séparer les opérations de base de données et en mémoire
La solution consiste à séparer la requête de base de données du traitement en mémoire. Cela implique d'abord d'exécuter la requête de base de données, puis d'effectuer le filtrage et la manipulation des données sur l'ensemble de données en mémoire résultant. La méthode AsEnumerable()
est essentielle ici. Il force l'exécution de la requête de base de données, renvoyant les résultats sous forme d'objet IEnumerable
, permettant aux opérations ultérieures de se produire entièrement en mémoire.
Voici le code corrigé :
<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() // Database query completes here .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>
En utilisant AsEnumerable()
, la requête de base de données est finalisée et l'instruction Select
suivante fonctionne uniquement sur les données extraites de la base de données, résolvant l'incompatibilité avec la collection ppCombined
en mémoire. Cela garantit que la requête s'exécute avec succès.
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!