【问题标题】:evaluate column name in linq where clause评估 linq where 子句中的列名
【发布时间】:2013-02-05 20:47:43
【问题描述】:

如果我在这里遗漏了一些明显的东西,我深表歉意....

我正在尝试自定义一种方法来创建 RadComboBox 过滤器,该过滤器可根据用户类型进行调整(基于 Telerik 演示)。我正在使用业务逻辑层来拉入我的数据源,然后我尝试使用 linq 来选择组合框 OnItemsRequested 的值,具体取决于哪个组合框发出了请求。我正在尝试根据发出请求的 GridColumn 过滤器来设置“where”子句中的参数。

这是我填写列表的代码:

private void list_ItemsRequested(object o, RadComboBoxItemsRequestedEventArgs e)
    {
        ((RadComboBox)o).DataTextField = this.DataField;
        ((RadComboBox)o).DataValueField = this.DataField;
        var employees = from emp in EmployeeBL.GetAllEmployees()
                        where emp.(this.UniqueName).Contains(e.Text)
                        select emp;
        ((RadComboBox)o).DataSource = employees;
        ((RadComboBox)o).DataBind();
    }

我需要将 UniqueName 作为参数转换为我的数据对象 (EmployeeDTO) 吗?

谢谢。

更新:: 感谢反馈,我在填充组合框列表方面取得了一些成功。但是,我认为我的 linq 声明中仍然存在错误。该列表是第一次构建的,但是,当我尝试进行“StartsWith”比较时,页面会抛出一个错误,指出 数据源不包含数据行,即使我肯定输入了“可找到的” " 字符串。

这是我现在拥有的。

private void list_ItemsRequested(RadComboBox o, RadComboBoxItemsRequestedEventArgs e)
    {
        o.DataTextField = this.DataField;
        o.DataValueField = this.DataField;

        DataTable dt = EmployeeBL.GetAllEmployees().AsDataTable();

        IEnumerable<DataRow> query =
            from emp in dt.AsEnumerable()
            where emp.Field<String>(this.UniqueName).StartsWith(e.Text)
            select emp;

        DataTable boundTable = query.CopyToDataTable<DataRow>();
        o.DataSource = boundTable;
        o.DataBind();
    }

【问题讨论】:

  • 您真的应该只转换一次o 并在整个方法中使用输入的结果。这是一个巨大的性能损失,也是一个真正的阅读障碍。
  • ....更不用说代码的可读性了:)
  • 我很欣赏速度和风格点 cmets。 (我对此很陌生。)关于如何让“this.UniqueName”在 WHERE 子句中进行评估有什么想法吗?
  • GetAllEmployees 返回什么类型?我假设IQueryable&lt;Employee&gt; 但想确认一下。
  • @DStanley,它返回一个List&lt;EmployeeDTO&gt;

标签: linq where dto


【解决方案1】:

没有内置方法。你有一些选择:

  • 使用动态 Linq 查询库,例如 ScottGu's
  • 使用属性名对build an Expression的反射
  • 使用switch 语句从已知的属性列表中选择一个表达式(易于编码,动态性较低)
  • 使用CopyToDataTable 扩展方法创建一个确实 支持通过DataViews 进行基于字符串的排序/过滤的数据表

【讨论】:

  • 谢谢,我忘记了 ToDataTable 扩展。我会试试看。
【解决方案2】:

您是否尝试在每个员工上调用this.UniqueName 中命名的方法,并查看结果是否包含文本?是这样,你可以使用反射。

如果您确定oRadComboBox,那么也可以这样传入。

private void list_ItemsRequested(RadComboBox o, RadComboBoxItemsRequestedEventArgs e)
{
    o.DataTextField = this.DataField;
    o.DataValueField = this.DataField;

    PropertyInfo property = typeof(EmployeeDTO).GetProperty(this.UniqueName);
    var employees = from emp in EmployeeBL.GetAllEmployees()
                    where ((IQueryable<string>)(property.GetValue(emp))).Contains(e.Text)
                    select emp;
    o.DataSource = employees;

    o.DataBind();
}

【讨论】:

  • 我假设 this.UniqueName 引用了一个属性名称,因为 OP 声明它是网格中的一列。
  • 谢谢@DStanley。我已将其更改为属性并添加了缺少的演员表。
  • 我从未使用过反射......但我确实尝试了你的建议,而 Intellisense 说property 没有 GetValue 方法。我基本上是在尝试将员工列表加载到组合框中(配置为过滤值列表),当用户开始键入时,该值在 where 子句中进行评估。我从GetAllEmployees() 返回的是一个 List。不确定这是否会影响PropertyInfo 冲突。谢谢。
  • Property 类型确实有一个GetValue 方法。该错误可能是说被调用的实际属性不存在。此代码期望在EmployeeDTO 中有一个IQueryable&lt;string&gt; 类型的属性,其名称在您的UniqueName 中指定。
  • @MatthewStrawbridge 我对此完全陌生,但我真的很想了解您的建议,b/c 我想我很接近。如果可以的话,你能告诉我你的例子中发生了什么吗?我认为,正如您所建议的,Property 上的 EmployeeDTO 查找与列值中实际匹配的内容之间存在冲突。我希望在列中的值之间进行匹配(例如,FullName 既是 EmployeeDTOProperty 又是 GridColumn thisUniqueName ) 和文本 (e.Text) 被输入到 ComboBox
猜你喜欢
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多