LINQ To SQL 动态选择

5

有人能向我展示如何在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));
                }

1
关于sExtFilters变量的作用域:https://dev59.com/VXNA5IYBdhLWcg3wF5uO#1095770 - Mehrdad Afshari
我正在删除 dynamic-linq 标签,因为该标签是指 动态查询扩展(注意:这对你在这里没有帮助,很遗憾)。 - Aaronaught
感谢您提醒我关于作用域陷阱的问题。 - mcass20
2个回答

3
短回答是不要
方法必须具有已知的特定返回类型。该类型可以是System.Object,但此时您必须使用大量丑陋的反射代码来获取成员。在这种情况下,您还必须使用大量丑陋的表达式树代码来生成返回值。
如果您正在尝试在UI端动态生成列,请停止这样做。在设计时定义列,然后只显示/隐藏实际需要/希望用户看到的列。让您的查询返回可能可见的所有列。
除非您注意到选择所有数据列存在严重性能问题(在这种情况下,您可能在数据库级别上存在非覆盖索引问题),否则您将更喜欢这种方法。动态生成谓词和排序顺序是完全可以的,但您确实不希望在输出列表上执行此操作。
一些评论迫使我认真考虑我是否正确地暗示动态输出列表实际上是可能的,我得出结论,尽管这是一种危险的逆流而游的想法,但它确实是可能的。为了完成这个特技,你需要:
  1. 使用Reflection.Emit生成一个新类型。
  2. 生成一个表达式树,通过使用Expression.MemberInit来初始化它。
  3. 编译表达式并将其传递给Select方法。
  4. 从您的方法返回弱类型的System.Object,并使用反射按名称访问成员。

这不是我希望在生产代码中看到的东西,但是你有它-它是可能的。


这不是我寻求的答案,但你提出了一个有趣的观点。 - mcass20
@Adam:理论上来说,如果你为“Select”动态构建一个表达式树是可能的。我说“理论上”是因为我没有尝试过,也不会尝试。 ;) - Aaronaught
1
@Aaronaught:确实。现在,轮到我的下一个招数了,我将使用强类型ORM工具来执行完全动态的(无论是条件还是结果)查询! - Adam Robinson
不需要生成新的类型。只需将每一行投射到一个 XmlElement 中。 - Amy B
我们使用动态构建的表达式树调用Select()来创建实体的自我投影,以清除用户可能没有权限或不打算绑定到(他们指定一个投影)的属性,然后从我们的服务中返回它。不幸的是,Linq to SQL明确禁止自我投影,因此我们实际上是将其投影到派生类型(一种不添加任何内容到基本实体类型的类型)。有趣的是,自我投影现在被吹捧为WCF数据服务的一个功能,请参见http://msdn.microsoft.com/en-us/magazine/ee336312.aspx。 - luksan
显示剩余5条评论

1
你不需要在查询级别这样做(这样做将非常困难,因为你需要在运行时动态创建一个类型)......在GridView本身中明确声明要显示的列会更容易处理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接