2010-07-15 4 views
2

J'ai la requête suivante:Comment générer une meilleure SQL à partir Linq2Sql requête

var data = from d in dc.GAMEs 
    where (d.GAMEDATE + d.GAMETIME.Value.TimeOfDay) >= DateTime.Now select d; 

Cela génère une horendous recherche SQL, en regardant quelque chose comme ceci:

SELECT {...} WHERE DATEADD(ms, ((CONVERT(BigInt,((CONVERT(BigInt,DATEPART(HOUR, [t0].[GAMETIME]))) * 36000000000) + ((CONVERT(BigInt,DATEPART(MINUTE, [t0].[GAMETIME]))) * 600000000) + ((CONVERT(BigInt,DATEPART(SECOND, [t0].[GAMETIME]))) * 10000000) + ((CONVERT(BigInt,DATEPART(MILLISECOND, [t0].[GAMETIME]))) * 10000)))/10000) % 86400000, CONVERT(DateTime,DATEADD(day, (CONVERT(BigInt,((CONVERT(BigInt,DATEPART(HOUR, [t0].[GAMETIME]))) * 36000000000) + ((CONVERT(BigInt,DATEPART(MINUTE, [t0].[GAMETIME]))) * 600000000) + ((CONVERT(BigInt,DATEPART(SECOND, [t0].[GAMETIME]))) * 10000000) + ((CONVERT(BigInt,DATEPART(MILLISECOND, [t0].[GAMETIME]))) * 10000)))/864000000000, [t0].[GAMEDATE]))) >= @p0 

Quelle est la raison de ce massif quantité de SQL? Et y a-t-il une meilleure façon d'y faire face?

EDIT:

Je n'ai aucun contrôle sur le schéma. C'est ce que c'est, et je dois y faire face.

Répondre

2

Si vous pouvez modifier le schéma alors la meilleure façon de traiter avec elle est d'utiliser une seule colonne datetime2 au lieu de date et time séparer les champs. Votre requête actuelle ne pourra pas utiliser un index.

Sinon, vous pouvez essayer de réécrire la requête comme suit:

DateTime now = DateTime.Now; 
var data = from d in dc.GAMEs 
    where (d.GAMEDATE > now.Date) || 
      (d.GAMEDATE == now.Date && d.GAMETIME.Value.TimeOfDay >= now.TimeOfDay) 
    select d; 

Le SQL généré par cette requête pourrait être un peu plus lisible et peut-être aussi plus efficace. D'un autre côté, du point de vue du programmeur, il est plus important que le code source soit lisible que le SQL généré soit lisible. Si les performances ne vous préoccupent pas, vous pouvez laisser votre code tel quel et admettre que le SQL généré est moche et ne vous inquiétez pas.

+0

J'aimerais, mais ne peut pas. Cela briserait l'application existante pour laquelle nous n'avons aucune source. –

+0

@Mystere Man: Avez-vous envisagé d'ajouter datetime2 en tant que colonne calculée? Si vous persistez, vous pouvez même l'indexer. Ajouter une colonne supplémentaire sans modifier les colonnes existantes a une chance raisonnable de ne pas casser l'application existante (bien que vous aurez besoin de la tester complètement pour être sûr). http://msdn.microsoft.com/en-us/library/ms191250.aspx –

+0

Mon hypothèse était qu'en raison de tous les calculs dans le SQL généré, il serait considérablement plus lent. Non, je n'ai pas mesuré cela, et les citations de Knuth à part, je préfère sql plus propre quand c'est possible. –

0

Comme alternative (depuis plus à l'extérieur OR est la bête noire des index)

DateTime now = DateTime.Now; 
DateTime today = now.Date; 
TimeSpan timeOfDay = now.TimeOfDay; 

var data = 
    from d in dc.GAMEs 
    where d.GAMEDATE >= today 
    && (d.GAMEDATE > today || d.GAMETIME.Value.TimeOfDay >= timeOfDay) 
    select d; 
Questions connexes