【问题标题】:How to run a query for each entry in an array?如何对数组中的每个条目运行查询?
【发布时间】:2013-09-20 22:54:12
【问题描述】:

我正在尝试使用 LINQ to SQL 根据数组中的值查询相应的数据,但遇到了问题。我正在阅读这些线程,但不确定它们是否真的是我想要做的,以及它们是否是如何实现它们的:

LINQ equivalent of foreach for IEnumerable<T>

Linq style "For Each"

我有我的字符串数组'lines[]',我如何为每个条目运行以下查询,并以允许我以连贯方式输出它们的方式存储结果。 这里又是我的数组的一个示例: 例子: Z1234 Z2345 ZAF38383

//some non working code
List<string> results = new List<string>();

var thisQuery = from c in myContext.SpecificTable
where c.itemNumber == (foreach (string i in lines))
select c;

foreach (var result in thisQuery)
{
    results.Add(result);
}

列表创建很好,我认为写入列表也可以,但我不知道如何为数组中的每个项目运行查询?

我的数组中的每个条目都以 Z 开头,然后将包含任何重要的字母数字字符排列。示例:Z3333

数组中的每个条目对应于我的数据库“SpecificTable”中的表中的一个条目。我想在该表中返回与该值有关的所有内容,然后我可以输出该数据的详细信息。

示例: 我想从查询 Z1234 开始,当在“SpecificTable”中找到 Z1234 时,我希望能够像这样输出各种详细信息:

foreach (var res in thisQuery)
{
   //each result from the query (total of 3 from the example) will now show their Description in a messagebox.
   MessageBox.Show("Description:" + res.Description.ToString());
 }

通过使用循环,我希望能够根据初始数组创建所有结果的列表,并输出它们对应的各种值,例如'Description'。

如果这仍然不够信息,请让我知道我可以提供什么更清楚。

【问题讨论】:

  • foreach (var result in thisQuery) { results.Add(result); } 可以简写为results = thisQuery.ToList();

标签: c# sql arrays linq loops


【解决方案1】:

试试:

这将循环 myContext.SpecificTable 中的行并创建一个内部循环来检查行内是否存在匹配项。

var thisQuery = from c in myContext.SpecificTable
                from i in lines
                where c.itemNumber == i
                select c;

或者这个:

这将做同样的事情,只有第二个“迭代器”在包含中完成。

var thisQuery = from c in myContext.SpecificTable
                where  lines.Contains(c.itemNumber)
                select c;

我认为最好将 db 查询放在外循环中,因为您不希望行中的每个项目都使用“tablescan”。

所以它只会做一个“tablescan”,并尝试在行中找到匹配项。

我认为如果你尝试这样的事情会加快速度:

var linesHashSet = new HashSet<string>(lines);

var thisQuery = from c in myContext.SpecificTable
                where  linesHashSet.Contains(c.itemNumber)
                select c;

这里它将在第二次迭代中使用一个哈希集(索引列表)


更新:

可以在客户端迭代行,如下所示:

var thisQuery = from c in myContext.SpecificTable.ToArray()
                where  lines.Contains(c.itemNumber)
                select c;

但这会对性能产生影响。 我建议你试试中间那个。

【讨论】:

  • 当我尝试您的第一个查询时,它返回了以下错误:Local sequence cannot be used in LINQ to SQL implementations of query operator except the Contains operator。我真的不知道那是关于什么的。当我使用行 'wherelinesHashSet.ToList().Contains.... 时,我得到最后一个示例至少没有错误,但是我后来查看 thisQuery 内容的调用没有产生任何结果,我想这意味着我的查询是'实际上没有选择任何东西?
  • Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator. 表示它想为整个 linq 语句创建一个查询,但它无法将from i in lines 转换为 sql 语句。建议你用中间那个。是否可以监控生成了什么sql语句?我会在我的答案中添加一些内容。
  • 关于空结果,我不知道数据是什么样的,所以我无法预测结果。
  • 第二个查询是常用的方法(如果我对OP理解得很好,这个问题就不太清楚了)。首先转换为哈希集是没有用的,因为 lines 数组仅在查询提供程序生成 IN 子句时被枚举一次。 @FuzzEvans,如果这不能产生正确的结果,您需要提供有关输入和预期输出的更多详细信息。
  • HashSet 仅在客户端执行查询时使用。 (IEnemerable 而不是 IQueryable)
【解决方案2】:

不确定我是否正确理解了您的问题,但您想将 SpecificTable 中的条目与“lines”数组连接起来,并将结果作为列表输出?

var results = myContext.SpecificTable.Select(c => lines.Contains(c.ItemNumber)).ToList();
foreach(var result in results)
{
    Console.WriteLine(string.format("{0}:{1}", "Description", result.Description));
}

如果您只需要特定属性,则可以返回匿名对象列表。

var results = myContext.SpecificTable.Where(c => lines.Contains(c.ItemNumber)).Select(c => new {c.ItemNumber, c.Description}).ToList();
foreach(var result in results)
{
    Console.WriteLine(string.format("{0}:{1}", "Description", result.Description));
}

【讨论】:

  • 'results' 已经被放入列表的地方,这不是使它无法处理对'result.Description' 的最后调用吗?在我的项目中尝试无法识别 result.Description,我想知道这是否是原因?
  • 我猜“结果”将是 IEnumerable> 类型。最简单的找出方法是放置一个断点,然后找到 Select 查询的返回类型。本质上,如果单个元素的类型不是您想要的,您可以提取特定属性。你的“SpecificTable”对象有描述属性吗?
猜你喜欢
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
  • 2017-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多