2009-11-17 19 views
0

Je me bats avec une colonne datetime annulable [DateInsp] dans une application ASP.NET qui utilise SubSonic3, Linq, MS SQL Server 2005.groupement Linq par datetime annulable et utilisant comme critères

J'ai eu tout cela de travail lorsque la colonne datetime [DateInsp] n'autorise pas les valeurs NULL. Une nouvelle exigence m'a forcé à définir la colonne [DateInsp] pour autoriser les valeurs nulles et maintenant j'ai du mal à faire fonctionner correctement cette fonctionnalité.

Problème 1: Je dois d'abord rendre une liste déroulante des 7 dernières dates d'inspection pour un inspecteur donné (ce qui est une liste groupée des 7 dates les plus récentes pour l'inspecteur). Voici le TSQL que je dois convertir à la syntaxe LINQ:

declare @InspectorID varchar(5) 
set @InspectorID = 'GPA' 

select top 7 convert(nvarchar(30), [DateInsp], 101) InspectedDate 
from [dbo].[IncomingInspection] 
group by [InspectorID], convert(nvarchar(30), [DateInsp], 101) 
having [InspectorID] = @InspectorID 
order by convert(nvarchar(30), [DateInsp], 101) desc 

Si je ne peux pas obtenir ce travail correctement LINQ, mais je peux/pourrait construire une procédure stockée pour retourner la liste des dates et que jeter dans une liste déroulante. C'est suffisant. Je me suis battu avec la syntaxe Linq donc toute aide dans ce domaine est grandement appréciée.

Problème 2: J'ai besoin d'utiliser la date sélectionnée dans la liste déroulante mentionnée ci-dessus pour tirer les enregistrements corrects pour cet inspecteur et la date correcte. Encore une fois, ceci est un champ datetime nullable et c'est un vrai point de friction pour moi.

Voici était la syntaxe LINQ originale qui a accompli l'exigence avant que je devais changer le champ datetime pour allow nulls:

Dim query = (From i In db.IncomingInspections _ 
     Where i.InspectorID = User.Identity.Name _ 
     Group By Key = New With {i.DateInsp} Into Group _ 
     Order By Key.DateInsp Descending _ 
     Select Key = New With {.DateInsp = Key.DateInsp.ToShortDateString}).Take(7) 

Cette application est écrit en VB.NET et utilise une syntaxe LINQ qui à la fois faire mon mal de tete. Si vous pouvez offrir la syntaxe C# pour cela, je peux le traduire moi-même sur VB.NET.

EDIT:

Pour une raison quelconque, je ne peux pas utiliser la propriété .Value; Je reçois: Le membre « Value » est pas pris en charge

je reçois: « syntaxe incorrecte près de « < ». » si j'essaie d'ajouter la comparaison de date à la clause where aussi.

FIN EDIT

Merci Beaucoup,

Josh

+0

J'ai omis de mentionner que la colonne DateInspected a un composant de temps que je dois omettre lors du remplissage de la liste déroulante. En outre, l'utilisateur aura toujours une date sélectionnée dans la liste déroulante. La liste déroulante aura une liste des 7 dernières dates (date seulement, pas de temps) des dossiers d'inspection sur lesquels ils ont travaillé. La date sélectionnée sera utilisée dans l'énoncé de critère de la deuxième requête. Note: la clause de critères devra tenir compte de la date sélectionnée (sans temps). J'ai essayé d'utiliser une plage de dates comme suit: Et (x.DateInsp> = RangeStart Et x.DateInsp <= RangeEnd) sans succès ... – joshblair

Répondre

1

je suis allé de l'avant et utilisé 2 procédures stockées pour résoudre ce problème en éliminant la nécessité de la syntaxe LINQ ici:

Voici le TSQL que je l'habitude d'obtenir une liste des 7 dernières dates d'inspection (w/seule partie date du champ datetime:

select top 7 convert(nvarchar(30), [DateInsp], 101) InspectedDate 
from [dbo].[IncomingInspection] 
group by [InspectorID], convert(nvarchar(30), [DateInsp], 101) 
having [InspectorID] = @InspectorID 
order by convert(nvarchar(30), [DateInsp], 101) desc 

Voici le tsql que je l'habitude de saisir une liste filtrée des dossiers d'inspection pour l'inspecteur et la date d'inspection sélectionnée dans le menu déroulant (en utilisant uniquement la partie de date dans le énoncé de critères):

select [ID] 
,[InspectorID] 
,[DateInsp] 
-- (more fields here) 
from [dbo].[IncomingInspection] 
where [InspectorID] = @InspectorID and DATEADD(dd, 0, DATEDIFF(dd, 0, [DateInsp])) = DATEADD(dd, 0, DATEDIFF(dd, 0, @DateFilter)) 

Parfois, je dois juste aller avec des œuvres plutôt que ce qui est nouveau et brillant. Je me suis parfois battu avec les choses les plus simples de Linq et je pense que c'est à la fois parce que Linq est nouveau pour moi et que j'ai battu la tête sur la syntaxe VB.NET, surtout quand je l'ai combiné avec Linq.

0

Désolé pour répondre en C#, mais voici mon interprétation de vos requêtes:

Problème n ° 1.

Vous utilisez ayant dans la question, ainsi que de convertir les dates-heures en chaînes. Je n'ai vu aucun besoin de ces opérations.

string inspectorId = "GPA"; 

List<DateTime?> someDates = db.IncomingInspection 
    .Where(insp => insp.InspectorId == inspectorId) 
    .Select(insp => insp.InspectedDate) 
    .Distinct() 
    .OrderByDescending(d => d) 
    .Take(7) 
    .ToList(); 

Problème n ° 2.

Il y a deux cas: soit vous avez une valeur nulle de l'utilisateur, soit vous avez une valeur. Il est simple d'écrire une requête pour cibler chaque cas. Si simple, que j'ai l'impression d'avoir mal interprété l'intention ici.

DateTime? selectedDate = control.SelectedValue; 

List<IncomingInspection> someRecords = null; 

if (selectedDate.HasValue()) 
{ 
    DateTime selectedDateValue = selectedDate.Value; 
    someRecords = db.IncomingInspection 
    .Where(insp => insp.InspectorId == inspectorId) 
    .Where(insp => insp.InspectedDate == selectedDateValue) 
    .ToList(); 
} 
else 
{ 
    someRecords = db.IncomingInspection 
    .Where(insp => insp.InspectorId == inspectorId) 
    .Where(insp => insp.InspectedDate == null) 
    .ToList(); 
} 
+0

Merci pour votre réponse. J'ai omis de mentionner que la colonne DateInspected a un composant temporel que je dois omettre lors du remplissage de la liste déroulante. En outre, l'utilisateur aura toujours une date sélectionnée dans la liste déroulante. La liste déroulante aura une liste des 7 dernières dates (date seulement, pas de temps) des dossiers d'inspection sur lesquels ils ont travaillé. La date sélectionnée sera utilisée dans l'énoncé de critère de la deuxième requête. Note: la clause de critères devra tenir compte de la date sélectionnée (sans temps). J'ai essayé d'utiliser une plage de dates comme suit: Et (x.DateInsp> = RangeStart Et x.DateInsp <= RangeEnd) – joshblair