2010-04-26 3 views
0

Cela repousse probablement un peu les limites de Linq-to-Sql, mais étant donné la polyvalence de cette requête, je pensais que je le ferais.Passage d'une clause WHERE pour une requête Linq-to-Sql en tant que paramètre

J'ai 3 requêtes qui sélectionnent des informations identiques et ne diffèrent que dans la clause, maintenant je sais que je peux passer un délégué mais cela ne me permet que de filtrer les résultats déjà retournés, mais je veux construire la requête via paramètre pour assurer l'efficacité.

Voici la requête:

from row in DataContext.PublishedEvents 
join link in DataContext.PublishedEvent_EventDateTimes 
    on row.guid equals link.container 
join time in DataContext.EventDateTimes on link.item equals time.guid 
where row.ApprovalStatus == "Approved" 
    && row.EventType == "Event" 
    && time.StartDate <= DateTime.Now.Date.AddDays(1) 
    && (!time.EndDate.HasValue || time.EndDate.Value >= DateTime.Now.Date.AddDays(1)) 
orderby time.StartDate 
select new EventDetails 
{ 
    Title = row.EventName, 
    Description = TrimDescription(row.Description) 
}; 

Le code que je veux appliquer via un paramètre serait:

time.StartDate <= DateTime.Now.Date.AddDays(1) && 
(!time.EndDate.HasValue || time.EndDate.Value >= DateTime.Now.Date.AddDays(1)) 

Est-ce possible? Je ne pense pas que ce soit mais je pensais d'abord vérifier.

Merci

Répondre

2

Oui c'est.

var times = DataContext.EventDateTimes; 
if (cond) 
    times = times.Where(time => time.StartDate <= ...); 

from row in ... join time in times ... 
+0

Ah, cela semble faisable, je vais essayer, merci. – Mantorok

2

Ce que vous pouvez faire est de passer un objet qui permet de filtrer un IQueryable. Lorsque vous faites cela, vous pouvez écrire du code comme ceci est votre couche de service:

public Person[] GetAllPersons(IEntityFilter<Person> filter) 
{ 
    IQueryable<Person> query = this.db.Persons; 

    query = filter.Filter(query); 

    return query.ToArray(); 
} 

et dans votre couche d'appel, vous pouvez définir un filtre comme ceci:

IEntityFilter<Person> filter = 
    from person in EntityFilter<Person>.AsQueryable() 
    where person.Name.StartsWith("a") 
    where person.Id < 100 
    select person; 

// or (same result, but without LINQyness) 
IEntityFilter<Person> filter = EntityFilter<Person> 
    .Where(p => p.Name.StartsWith("a")) 
    .Where(p => p.Id < 100); 

// Call the BL with the filter. 
var persons = BusinessLayer.GetAllPersons(filter); 

Vous pouvez trouver le code source une implémentation de ce EntityFilter<T>here (c'est environ 40 lignes de code) et comme article de blog à ce sujet here.

Veuillez noter que votre requête est un peu plus complexe que l'exemple que j'ai montré ici, donc cela pourrait prendre un peu plus de travail pour définir le bon filtre.