如何从对象数据源的 LINQ 查询中删除 NULL 列
本文关键字:查询 删除 NULL LINQ 对象 数据源 | 更新日期: 2023-09-27 18:31:04
正如问题所建议的那样,我想从 LINQ 查询中删除该列中的所有列,其中该列中的所有行都是空的。
目前,我正在使用 LINQ 使用所需的日期和网站筛选器运行初始查询,然后将一个 IEnumerable 对象返回到 GridView 中的对象数据源。这一切都很好用。
但是我在实现代码以删除空/NULL列时遇到困难(LINQ对我来说很新)。
这是我的工作代码,用于将 IEnumerable 返回到 ObjectDataSource:
public IEnumerable<WebApplication1.HL_Log> Select(string startDate, string endDate)
{
DateTime start = DateTime.Now.AddDays(-1);
DateTime end = DateTime.Now;
if (startDate != "01/01/1900")
{
DateTime.TryParse(startDate, out start);
}
if (endDate != "01/01/1900")
{
DateTime.TryParse(endDate, out end);
}
DataClasses1DataContext db = new DataClasses1DataContext();
var query = from h in db.HL_Logs
where h.ID_Location == 45
&& h.Time_Stamp >= start.Date
&& h.Time_Stamp <= end.Date.AddDays(1)
orderby h.Time_Stamp
select h;
return query;
}
到目前为止,我已经能够将结果转换为数据表并删除空列,就像我在使用数据表的其他项目中所做的那样,使用以下方法:
//Convert to a Datatable
DataTable dt = new DataTable();
dt = LINQToDataTable(query);
//Now remove the completely NULL columns
foreach(var column in dt.Columns.Cast<DataColumn>().ToArray())
{
if (dt.AsEnumerable().All(dr => dr.IsNull(column)))
dt.Columns.Remove(column);
}
但是我需要先将其转换回 IEnumerable,然后才能将其返回到我的 ObjectDataSource。所以真的我的问题是,我如何将数据表转换回 IEnumerable,或者我是否对此使用了非常低效的 app,如果是这样,实现我的结果的最佳方法是什么?
到目前为止,我的总体代码:
public IEnumerable<WebApplication1.HL_Log> Select(string startDate, string endDate)
{
DateTime start = DateTime.Now.AddDays(-1);
DateTime end = DateTime.Now;
if (startDate != "01/01/1900")
{
DateTime.TryParse(startDate, out start);
}
if (endDate != "01/01/1900")
{
DateTime.TryParse(endDate, out end);
}
DataClasses1DataContext db = new DataClasses1DataContext();
var query = from h in db.HL_Logs
where h.ID_Location == 45
&& h.Time_Stamp >= start.Date
&& h.Time_Stamp <= end.Date.AddDays(1)
orderby h.Time_Stamp
select h;
//Convert to a Datatable
DataTable dt = new DataTable();
dt = LINQToDataTable(query);
//Now remove the completely NULL columns
foreach(var column in dt.Columns.Cast<DataColumn>().ToArray())
{
if (dt.AsEnumerable().All(dr => dr.IsNull(column)))
dt.Columns.Remove(column);
}
//return ""HELP"";
}
感谢您的帮助!!
TL;DR
如果 Select
方法的使用者是 GridView DataBind()
,并且您需要一个完全动态的解决方案(例如,GridView
可以绑定到 HL_Log
以外的其他类型),则最好继续返回过滤后的DataTable
解决方案,因为很难针对未知类型的任意集合实现动态行隐藏。
老实说,我看不到更好、通用的方式来实现您已经在做的事情 - 需要 AFAIK 元数据,如 DataTable
、Xml
或ExpandoObject
?
更详细
由于您的方法返回强类型实体 ( IEnumerable<WebApplication1.HL_Log>
) 的枚举,因此您不能有选择地从实体中"删除"属性或字段 - HL_Log
的所有实例都将具有所有属性。我假设您当前已将AutoGenerateColumns
设置为在 GridView 上true
,因此需要修剪源代码中无用的列。 根据数据库列的所有值是否为空来投影不同类型的方法也很困难/乏味(例如,尝试返回 IEnumerable 并向 ExpandoObject
动态添加属性)。
此方法的替代方法是将column
隐藏在GridView
作为表示层关注点。但是请注意,这意味着您需要将AutoGenerateColumns
设置更改为false
(此处的原因),并显式检查Hl_Log
的所有可见属性
var hlLogs = myObject.Select(someStartDate, someEndDate).ToList();
if (hlLogs.All(hl => hl.Property1 == null))
{
myGridView.Columns["Property1"].Visible = false;
}
// Same for Property2, etc.
当然,这可能很快就会变得乏味。