如果您明确地想要使用LINQ动态查询库,那么我的答案不会是您想要的,但是如果您想要您想要的行为,并且您很乐意使用常规的LINQ,那么我认为我可以帮助您。
基本上我创造了一个
EntryGrouper
类,它处理按下拉列表中所选值分组的逻辑,我假定变量
section
,
page
和;
module
保持这些价值观。我也认为
ObjectContext.OmniturePageModules
是可枚举的类型
Entry
.
所以您的LINQ查询现在变成了这两个:
var entries = (from entry in ObjectContext.OmniturePageModules
where entry.StartOfWeek >= startDate
&& entry.StartOfWeek <= endDate
&& (section == "Total" || section == "All" || entry.Section == section)
&& (page == "Total" || page == "All" || entry.Page == page)
&& (module == "Total" || module == "All" || entry.Module == module)
select entry).ToArray(); // Force query execution
var grouping = from entry in entries
let grouper = new EntryGrouper(entry, section, page, module)
group entry by grouper into entryGroup
select new
{
SeriesName = entryGroup.Key.SeriesName,
Week = entryGroup.Key.StartOfWeek,
Clicks = entryGroup.Sum(p => p.Clicks),
};
第一个查询用于强制对数据库执行简单的select查询,并仅返回要分组的记录。一般来说
group by
查询多次调用数据库,因此以这种方式进行查询通常要快得多。
第二个查询通过创建
入口石斑鱼
类作为分组键。
我已经包括了
SeriesName
中的属性
入口石斑鱼
类,以便在一个位置整齐地定义所有分组逻辑。
现在,
入口石斑鱼
类非常大,因为为了允许分组工作,它需要具有
StartOfWeek
,
Section
,
Page
和;
Module
,并包含
Equals
和;
GetHashCode
方法,并实现
IEquatable<Entry>
接口。
这里是:
public class EntryGrouper : IEquatable<Entry>
{
private Entry _entry;
private string _section;
private string _page;
private string _module;
public EntryGrouper(Entry entry, string section, string page, string module)
{
_entry = entry;
_section = section;
_page = page;
_module = module;
}
public string SeriesName
{
get
{
return String.Format("{0}:{1}:{2}", this.Section, this.Page, this.Module);
}
}
public DateTime StartOfWeek
{
get
{
return _entry.StartOfWeek;
}
}
public string Section
{
get
{
if (_section == "Total" || _section == "All")
return _section;
return _entry.Section;
}
}
public string Page
{
get
{
if (_page == "Total" || _page == "All")
return _page;
return _entry.Page;
}
}
public string Module
{
get
{
if (_module == "Total" || _module == "All")
return _module;
return _entry.Module;
}
}
public override bool Equals(object other)
{
if (other is Entry)
return this.Equals((Entry)other);
return false;
}
public bool Equals(Entry other)
{
if (other == null)
return false;
if (!EqualityComparer<DateTime>.Default.Equals(this.StartOfWeek, other.StartOfWeek))
return false;
if (!EqualityComparer<string>.Default.Equals(this.Section, other.Section))
return false;
if (!EqualityComparer<string>.Default.Equals(this.Page, other.Page))
return false;
if (!EqualityComparer<string>.Default.Equals(this.Module, other.Module))
return false;
return true;
}
public override int GetHashCode()
{
var hash = 0;
hash ^= EqualityComparer<DateTime>.Default.GetHashCode(this.StartOfWeek);
hash ^= EqualityComparer<string>.Default.GetHashCode(this.Section);
hash ^= EqualityComparer<string>.Default.GetHashCode(this.Page);
hash ^= EqualityComparer<string>.Default.GetHashCode(this.Module);
return hash;
}
public override string ToString()
{
var template = "{{ StartOfWeek = {0}, Section = {1}, Page = {2}, Module = {3} }}";
return String.Format(template, this.StartOfWeek, this.Section, this.Page, this.Module);
}
}
此类的分组逻辑如下所示:
if (_page == "Total" || _page == "All")
return _page;
return _entry.Page;
如果我误解了下拉值是如何打开和关闭分组的,那么您应该只需要更改这些方法,但这段代码的关键在于,当分组打开时,它应该根据条目中的值返回一个组值,否则它应该为所有条目返回一个公共值。如果该值对于所有条目都是通用的,那么逻辑上它只创建一个与完全不分组相同的组。
如果要分组的下拉列表更多,则需要向
入口石斑鱼
班级。不要忘记将这些新属性添加到
等于
和;
方法
方法也是如此。
因此,这个逻辑表示您想要的动态分组。请告诉我我是否帮助过你,或者你是否需要更多的细节。
享受!