简体   繁体   English

将Linq-to-Sql查询的WHERE子句作为参数传递

[英]Passing a WHERE clause for a Linq-to-Sql query as a parameter

This is probably pushing the boundaries of Linq-to-Sql a bit but given how versatile it has been so far I thought I'd ask. 这可能会稍微限制Linq-to-Sql的界限,但是鉴于到目前为止它的用途如此广泛,我想我会问。

I have 3 queries that are selecting identical information and only differ in the where clause, now I know I can pass a delegate in but this only allows me to filter the results already returned, but I want to build up the query via parameter to ensure efficiency. 我有3个查询选择的信息相同,只是在where子句中有所不同,现在我知道我可以传递一个委托,但这只允许我过滤已经返回的结果,但是我想通过参数建立查询以确保效率。

Here is the query: 这是查询:

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)
};

The code I want to apply via a parameter would be: 我想通过参数应用的代码是:

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

Is this possible? 这可能吗? I don't think it is but thought I'd check out first. 我认为不是,但我想先退房。

Thanks 谢谢

Yes it is. 是的。

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

from row in ... join time in times ...

What you can do is passing an object that allows filtering an IQueryable. 您可以做的是传递一个允许过滤IQueryable的对象。 When you do this you can write code like this is your service layer: 当您执行此操作时,可以编写如下代码作为您的服务层:

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

    query = filter.Filter(query);

    return query.ToArray();
}

and in your calling layer, you can define a filter like this: 在调用层中,您可以定义一个过滤器,如下所示:

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);

You can find the source code of an implementation of this EntityFilter<T> here (it's around 40 lines of code) and as blog post about it here . 您可以在此处找到此EntityFilter<T>的实现的源代码(大约40行代码),并在此处找到有关内容的博客文章。

Please note that your query is a bit more complex than the example I've shown here, so it could take a bit more work to define the correct filter. 请注意,您的查询比我在此处显示的示例要复杂一些,因此定义正确的过滤器可能需要更多的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM