Question

J'ai deux tables, DH_MASTER et DH_ALIAS . DH_MASTER contient des informations sur une personne, y compris son nom. DH_ALIAS contient des enregistrements AKA concernant la personne. Les tables sont liées par le champ Opérateur qui est une clé primaire dans DH_MASTER .

Les utilisateurs souhaitent rechercher par le nom stocké dans DH_MASTER , ainsi que pour effectuer une recherche dans tous leurs alias connus. Si des correspondances sont trouvées dans DH_MASTER ou DH_ALIAS , l'entité DH_MASTER doit être renvoyée.

J'ai créé la requête ci-dessous qui devrait donner les résultats que j'ai décrits (renvoie toutes les lignes DH_MASTER contenant le DH_MASTER.Name == nom ou DH_MASTER.DH_ALIAs ( n) .Name == name ).

Cela fonctionne bien si je n’utilise qu’une seule des lignes .Contains . Peu importe lequel j'utilise. Mais l’exécution échoue lorsque j’essaie d’utiliser simultanément les DEUX.


    qry = From m In Context.DH_MASTERs _
          Where (m.Name.Contains(name)) _
              OrElse ((From a In m.DH_ALIAs _
                       Where a.Name.Contains(name)).Count() > 0) _
          Select m

La requête LinqToSQL évalue le code SQL suivant (affiché dans le visualiseur de requêtes SQL Server)


SELECT [t0].[Operator], [t0].[Name], [t0].[Version]
FROM [DHOWNER].[DH_MASTER] AS [t0]
WHERE ([t0].[Name] LIKE %smith%) OR (((
    SELECT COUNT(*)
    FROM [DHOWNER].[DH_ALIAS] AS [t1]
    WHERE ([t1].[Name] LIKE %smith%) AND ([t1].[Operator] = [t0].[Operator])
    )) > 0)

EDIT: vérification de la " Afficher l'original " La fenêtre du visualiseur de requêtes révèle la requête paramétrée comme prévu. Ce bloc de texte ci-dessous doit donc être ignoré.

Je ne sais pas s'il s'agit d'un problème ou non, mais le fichier `.Contains` correspond à une expression` LIKE` (ce qui est ce que je prévois), mais le paramètre n'est pas encapsulé dans des apostrophes.

Ce qui est intéressant, c’est que si je copie / colle la requête SQL dans l’analyseur de requêtes SQL 2005 et que j’ajoute les apostrophes autour des paramètres LIKE , il fonctionne parfaitement. En fait, il est rapide comme l'éclair, même avec plus de 2 millions de rangées.

Mais lorsque la requête LINQ est exécutée, l'application Web se verrouille pendant environ 31 secondes avant de finalement échouer avec cette erreur sur gv.DataBind: Une exception a été levée par la cible d'un appel.

Avec cette exception interne: Le délai d'attente a expiré. Le délai d'attente écoulé avant la fin de l'opération ou le serveur ne répond pas.

Quelqu'un sait-il pourquoi cela se produit et comment le comportement peut être contourné? Cela me rend fou parce que le SQL généré par LinqToSql fonctionne correctement dans l’analyseur de requêtes!

Mise à jour:

J'ai refactoré mon code en fonction des techniques de la réponse. Cela fonctionne!

qry = From m In qry _
 Where m.Name.Contains(name) OrElse _ 
 m.DH_ALIAs.Any(Function(aliasRec) aliasRec.Name.Contains(name)) _ 
Select m
Était-ce utile?

La solution

Cela pourrait ne pas être approprié, car votre problème est différent, mais je me souviens d'un problème dans l'un de mes programmes: Contains () ne fonctionnerait pas (dans mon cas, cela jetterait une Exception lors de l'évaluation), alors peut-être que Contains- la méthode est un peu cassée.

j'ai remplacé

result.Contains( x )

avec

result.Any( p => p == x )

qui a fonctionné.

Pouvez-vous essayer si cela fonctionne? Au moins, cela pourrait être un pas dans la bonne direction.

Autres conseils

Linq to sql ne spécifie pas de valeurs directement dans la requête, il utilise des paramètres. Êtes-vous sûr que la valeur du paramètre contient se trouve directement dans le sql?

Quoi qu'il en soit, le délai d'attente est probablement dû à un blocage: la requête veut lire une ligne d'une table qui est verrouillée par une autre requête / transaction (insertion / mise à jour) et cette requête prend apparemment plus de temps.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top