LINQ To SQL动态选择

mca*_*s20 5 c# asp.net linq-to-sql

有人可以告诉我如何在LINQ To SQL语句中指示我希望在运行时返回哪些列?

我允许用户在复选框列表中选择项目,这些项目表示他们希望在绑定到L2S查询结果的网格视图中显示的列.

我能够动态生成WHERE子句但无法对SELECT片段执行相同的操作.这是一个示例:

var query = from log in context.Logs select log;
                query = query.Where(Log => Log.Timestamp > CustomReport.ReportDateStart);
                query = query.Where(Log => Log.Timestamp < CustomReport.ReportDateEnd);
                query = query.Where(Log => Log.ProcessName == CustomReport.ProcessName);

                foreach (Pair filter in CustomReport.ExtColsToFilter)
                {
                    sExtFilters = "<key>" + filter.First + "</key><value>" + filter.Second + "</value>";
                    query = query.Where(Log => Log.FormattedMessage.Contains(sExtFilters));
                }
Run Code Online (Sandbox Code Playgroud)

Aar*_*ght 3

简短的回答是

方法必须具有已知的特定返回类型。该类型可以是System.Object,但是您必须使用大量丑陋的反射代码来实际获取成员。在这种情况下,你还必须使用很多丑陋的反射用于生成返回值的表达式树代码。

如果您尝试在 UI 端动态生成列 - 请停止这样做。在设计时定义列,然后只需显示/隐藏您实际需要/希望用户看到的列。让您的查询返回所有可能可见的列。

除非您注意到选择所有数据列时存在严重的性能问题(在这种情况下,您可能在数据库级别存在非覆盖索引问题),否则使用此方法会更好。动态生成谓词和排序顺序是完全可以的,但您确实不想对输出列表执行此操作。


有些评论迫使我认真考虑我的暗示是否正确,即动态输出列表实际上是可能的,我的结论是它是正确的,尽管这是一个危险的与当前想法相反的想法。为了完成这个特技,你必须:

  1. 使用Reflection.Emit生成新类型。
  2. 生成一个表达式树,并使用Expression.MemberInit对其进行初始化。
  3. 编译表达式并将其传递给Select方法。
  4. 从您的方法返回弱类型System.Object并使用反射按名称访问成员。

这不是我想在生产代码中看到的那种事情,但你已经有了——这是可能的。