Des requêtes apparemment équivalentes dans LINQ et SQL renvoient des résultats différents

Je ne sais pas pourquoi cela a été lié comme une dupe. La question est très différente. La réponse est différente. Je ne sais pas quoi changer. Si quelqu’un voit ce que je manque, s’il vous plaît faites le moi savoir …

J’obtiens un nombre différent de résultats en utilisant ces deux requêtes. Après l’avoir analysée pendant quelques heures, je dois jeter l’éponge, en admettant que je ne peux pas voir la différence de signification. Depuis que mon arsenal d’approches est vidé, je demande de l’aide.

LINQ

List result = context.Unos .Join(context.Duos, uno => uno.CommonId, duo => duo.CommonId, (uno, duo) => new { Uno = uno, Duo = duo }) .Where(item => item.Uno.Amount > 0 && item.Duo.Type == 2) .Select(item => item.Uno) .ToList(); 

SQL

 select * from Uno as u join Duo as d on d.CommonId = u.CommonId where u.Amount > 0 and d.Type = 2 

La question numéro un est de savoir si les deux déclarations ci-dessus sont effectivement équivalentes ou s’il me manque quelque chose. La question numéro deux est ce qui me manque (le cas échéant) ou comment la dépanner (si ce n’est pas le cas).

  1. Les appels sont effectués sur la même firebase database.
  2. Le nombre de résultats est très différent (142 et 1437).
  3. Les mêmes ensembles de résultats sont extraits pour la jointure interne.
  4. Uno et Duo sont des vues, pas des tables.

Que puis-je vérifier de plus?

modifier

Après un support formidable de la part de la communauté, nous avons établi que la requête LINQ pouvait être SQL’ized avec la commande suivante.

 var wtd = context.Unos .Join(context.Duos, uno => uno.CommonId, duo => duo.CommonId, (uno, duo) => new { Uno = uno, Duo = duo }) .Where(item => item.Uno.Amount > 0 && item.Duo.Type == 2) .Select(item => item.Uno) .ToSsortingng(); 

Ce qui est fou, c’est que l’exécution de cette chaîne dans SQL Manager produit 142 résultats (exactement comme la requête de l’exemple ci-dessus, la version SQL) et qu’elle n’en diffère que de manière insignifiante. Cependant, l’exécution de la requête LINQ elle-même produit 1437 résultats. Je suis trop confus pour même commencer à pleurer …

“SELECT \ r \ n [étendue1]. [Identificateur commun] AS [identificateur commun], \ r \ n [étendue 1]. [X] AS [X] \ r \ n FROM (SELECT \ n [Uno]. [Identificateur commun] [CommonId], \ n [Uno]. [X] AS [X] \ n DE [Finance]. [Uno] AS [Uno]) AS [Extension1] \ r \ n JOINDEMENT INTERNE (SELECT \ n [Duo]. [CommonId] AS [CommonId], \ n [Duo]. [Y] AS [Y], \ n [Duo]. [Z] AS [Z], \ n [Duo]. [Type] AS [Type], \ n [Duo]. [U] AS [U], \ n [Duo]. [V] AS [V] \ n DE [Finance]. [Duo] AS [Duo]) AS [Extension2] ON [Extension1] . [CommonId] = [Extent2]. [CommonId] \ r \ n WHERE ([Extent1]. [X]> cast (0 sous forme décimale (18))) AND ([Extent2]. [Type] = @ p__linq__0) ”

Cela se produit souvent lorsque les vues sont mappées dans Entity Framework. Contrairement aux tables de firebase database classiques, les vues n’ont souvent pas de valeurs de clé clairement uniques. Lorsque EF rencontre des lignes avec des valeurs de clé primaire identiques, il duplique simplement la ligne appartenant à la clé déjà connue. Dans les jointures, cela peut entraîner EF à générer davantage d’enregistrements enfants, car cette première ligne connue peut avoir plus d’enfants que la ligne réelle de la firebase database.

Le correctif consiste à s’assurer que la vue comporte un champ (ou une combinaison de champs) identifiant de manière unique une ligne. Et, bien sûr, dans EF, cela devrait être mappé en tant que clé primaire (éventuellement composite).

Je ne sais pas pourquoi EF affiche ce comportement. Je pense qu’il devrait être possible pour elle de lancer une exception qui matérialise les entités en double. Cette “fonctionnalité” provoque toujours beaucoup de confusion.

C’est un long plan, mais cette expression LINQ changerait-elle quelque chose?

 (from uno in context.Unos join duo in context.Duos on uno.CommonId equals duo.CommonId where uno.Amount > 0 && duo.Type == 2 select new {Uno = uno, Duo = duo} ).ToList() 

J’aime mieux cette forme car elle ressemble à la vraie requête SQL. D’une certaine manière, la déclaration de jointure dans votre LINQ me dérange …

Essayez de jeter un coup d’œil sur la requête que vous exécutez après l’exécution de LINQ dans la fenêtre IntelliTrace lors du débogage de cet endroit. Et puis comparez à votre SQL, je pense qu’ils sont différents. Si vous n’avez pas IntelliTrace, essayez Express Profiler . Il suffit de définir le nom de SQL Server, de cliquer sur Tracer et de l’espionner. J’espère que cela aidera!