jqGrid 选择列表的自定义 Linq 扩展方法

发布于 2024-10-28 01:20:34 字数 1591 浏览 3 评论 0原文

我有一个自定义方法来获取字符串,该字符串与 jqGrid 一起用于选择搜索列表。

所需的字符串格式为 ":All;value1:text1;value2:text2" 我目前有以下方法以可重用的方式实现此目的:

public static string jqGridFilterSelectList<TSource>(this IQueryable<TSource> source,Expression<Func<TSource, string>> selector)
{
     return string.Join(";", source.Select(selector).Distinct().ToArray()); 
}

这可以正常工作,但需要调用如下this:

string filterSelectList = service.GetAllUsers().jqGridFilterSelectList(x=>x.User + ":" + x.User);

我对必须使用像 x=>x.User + ":" + x.User 这样的选择器不太满意。我想将其转换为像这样的 2 个重载(伪代码!!)

// case where we want the value and text of the select list to be the same
public static string jqGridFilterSelectList<TSource>(this IQueryable<TSource> source,Expression<Func<TSource, string>> selector)
{
     return string.Join(";", source.Select(selector + ":" + selector).Distinct().ToArray()); 
     //obviously this won't work, but is it possible in some other way while executing it on the database still? Also is it possible to insist the selector only contains 1 column.
}

//case where we want different text and value
public static string jqGridFilterSelectList<TSource>(this IQueryable<TSource> source,Expression<Func<TSource, string>> textSelector,Expression<Func<TSource, string>> valueSelector)
{
     return string.Join(";", source.Select(valueSelector + ":" + textSelector).Distinct().ToArray()); 
}

我想我可能可以使用动态 linq 来实现这一点,但我有兴趣知道这是否可能。

I have a custom method for getting a string which is used with jqGrid for select lists for searching.

The required string format is ":All;value1:text1;value2:text2" I currently have the following method to achieve this in a reusable way:

public static string jqGridFilterSelectList<TSource>(this IQueryable<TSource> source,Expression<Func<TSource, string>> selector)
{
     return string.Join(";", source.Select(selector).Distinct().ToArray()); 
}

This works OK, but it requires the call to be like this:

string filterSelectList = service.GetAllUsers().jqGridFilterSelectList(x=>x.User + ":" + x.User);

I'm not very happy with having to use a selector like x=>x.User + ":" + x.User. I'd like to convert this into 2 overloads like this (pseudo code!!)

// case where we want the value and text of the select list to be the same
public static string jqGridFilterSelectList<TSource>(this IQueryable<TSource> source,Expression<Func<TSource, string>> selector)
{
     return string.Join(";", source.Select(selector + ":" + selector).Distinct().ToArray()); 
     //obviously this won't work, but is it possible in some other way while executing it on the database still? Also is it possible to insist the selector only contains 1 column.
}

//case where we want different text and value
public static string jqGridFilterSelectList<TSource>(this IQueryable<TSource> source,Expression<Func<TSource, string>> textSelector,Expression<Func<TSource, string>> valueSelector)
{
     return string.Join(";", source.Select(valueSelector + ":" + textSelector).Distinct().ToArray()); 
}

I suppose i could probably achieve this using dynamic linq, but i'm interested to know if this is possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

微暖i 2024-11-04 01:20:34

如果我理解正确的话,您几乎已经写好了:

public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> selector
)
{
     var compiled = selector.Compile();
     return string.Join(";", 
         source.Select(x => compiled(x) + ":" + compiled(x))
             .Distinct().ToArray()
     ); 
}

//case where we want different text and value
public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> textSelector, 
    Expression<Func<TSource, string>> valueSelector
)
{
     return string.Join(";", 
         source.Select(x => valueSelector.Compile()(x) + ":" + textSelector.Compile()(x))
             .Distinct().ToArray()
     ); 
}

只需要调用选择器函数即可获取值。
如果我误解了你的问题,请告诉我。

对于第二个问题,是否可以坚持选择器仅包含 1 列,简单的答案是否定的 - 选择器实际上可以是任何采用 的有效 Func TSource 并返回 string 并且没有办法限制里面可以做什么(除非你想检查提供的表达式树,但它会更复杂当然,比结果更重要)。

编辑:好的,这是某种 SQL LINQ 提供程序、实体框架吗?所以让我们尝试一些不同的做法。我不知道它是否有效,但让我们尝试先获取数据并连接对象:

public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> selector
)
{
     var compiled = selector.Compile();
     return string.Join(";", 
         source.Distinct().AsEnumerable()
             .Select(x => compiled(x) + ":" + compiled(x))
             .ToArray()
     ); 
}

//case where we want different text and value
public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> textSelector, 
    Expression<Func<TSource, string>> valueSelector
)
{
     return string.Join(";", 
         source.Distinct().AsEnumerable()
             .Select(x => valueSelector.Compile()(x) + ":" + textSelector.Compile()(x))
             .ToArray()
     ); 
}

附加的 ToEnumerable 调用在数据库和进程内处理之间切换。假设您的选择器是确定性的并且没有任何副作用,您可以对已获取的 TSource 项进行操作。

If I understand correctly, you've almost written it:

public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> selector
)
{
     var compiled = selector.Compile();
     return string.Join(";", 
         source.Select(x => compiled(x) + ":" + compiled(x))
             .Distinct().ToArray()
     ); 
}

//case where we want different text and value
public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> textSelector, 
    Expression<Func<TSource, string>> valueSelector
)
{
     return string.Join(";", 
         source.Select(x => valueSelector.Compile()(x) + ":" + textSelector.Compile()(x))
             .Distinct().ToArray()
     ); 
}

You just need to invoke your selector functions to get the values.
Let me know if I misunderstand your question.

For the second question, is it possible to insist the selector only contains 1 column, the simple answer is no - the selector can be virtually any valid Func that takes TSource and returns string and there's no way to limit what can be done inside (unless you want to examine the expression tree provided, but it will be more complicated than the outcome, for sure).

EDIT: OK, so this is some kind of SQL LINQ provider, Entity Framework? So let's try a bit differently. I don't know whether it'll work, but let's try to fetch the data first and concatenate on objects:

public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> selector
)
{
     var compiled = selector.Compile();
     return string.Join(";", 
         source.Distinct().AsEnumerable()
             .Select(x => compiled(x) + ":" + compiled(x))
             .ToArray()
     ); 
}

//case where we want different text and value
public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> textSelector, 
    Expression<Func<TSource, string>> valueSelector
)
{
     return string.Join(";", 
         source.Distinct().AsEnumerable()
             .Select(x => valueSelector.Compile()(x) + ":" + textSelector.Compile()(x))
             .ToArray()
     ); 
}

The additional ToEnumerable call switches between database an in-process processing. Assuming that your selectors are deterministic and don't have any side effects, you can operate on already fetched TSource items.

岁吢 2024-11-04 01:20:34

实现您需要的另一种方法是使用 搜索选项

在这种情况下,“:All;value1:text1;value2:text2”形式的 value 字符串只有在真正需要时才会被构建(直到第一次搜索)。当用户单击搜索对话框时,jqGrid 从 dataUrl 获取数据。服务器方法可以具有非常清晰的接口并返回 List 的 JSON 表示形式。在客户端,您定义 buildSelect 事件句柄,将 ["text1", "text2", ...] 转换为

有时您还应该使用 ajaxSelectOptions jqGrid 参数来自定义相应的$.ajax 请求获取选择列表的数据。

这种方式的优点是:

  1. 为选择列表提供数据的服务器方法可以有非常清晰的接口并且只返回List。
  2. 从服务器发送的数据大小将会减少,因为您不会发送“value1”和“text1”两次,因为这些值与您的情况中的文本相同。
  3. 您可以对 editoptions 使用相同的方法,以防万一您的网格使用任何编辑方法(内联、表单或单元格编辑)。在 buildSelect 的另一个实现中,您应该只跳过在选择列表中插入
  4. 仅当确实需要时才会构建选择元素的数据:在第一次使用搜索时。
  5. 来自服务器的选择列表的 HTTP GET 响应可以自动缓存,如果您需要在另一个网格中相同的选择数据,则可以直接从本地浏览器缓存获取先前的服务器响应。

One more way to implement what you need is to use dataUrl and buildSelect parameters of the searchoptions.

In the case the value string in the form ":All;value1:text1;value2:text2" will not be built till it is really needed (till the first searching). When the user click on the search dialog the jqGrid get the data from the dataUrl. The server method can have very clear interface and return JSON representation of List<string>. On the client side you define buildSelect event handle which convert the the ["text1", "text2", ...] to the <select>. It's all. An example the usage of this ways you can find here. In comparing with the example you need only add additional option <option value="">All</option> in the select element.

Sometimes you should additionally use ajaxSelectOptions jqGrid parameter to customize the corresponding $.ajax request which get the data for the select list.

The advantages of the way:

  1. The server method providing the data for select list can have very clear interface and return just List.
  2. The size of data send from the server will be reduced because you don't send the "value1" and "text1" twice because of the values are the same as the text in your case.
  3. You can use the same method for editoptions in case of your grid use any editing method (inline, form or cell editing). In another implementation of buildSelect you should only skip inserting of <option value="">All</option> in the select list.
  4. The data for select element will be build only if there really needed: at the first usage of searching.
  5. The HTTP GET response from the server for select list can be cached automatically and if you need the same select data in another grid the previous server response can be get directly from the local browser cache.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文