linq-to-sql Concat()抛出System.IndexOutofRangeException

时间:2011-03-15 00:18:59

标签: c# linq-to-sql

我正在使用linq-to-sql Concat()

来解决异常问题

我有两张桌子。 第一个表ParsedMessages具有以下字段

* ParsedMessageID (int)
* MessageTypeID (int)
* TextMessage (varchar(max)) 

第二个表ParsedMessageLinks具有以下字段

* ParsedMessageID (int)
* AnotherID (int)
* NumberOfOccurences (int)

这是我需要使用单个linq查询实现的,但我不确定它是否可能。

  • 通过联接,检索链接到某个AnotherID的ParsedMessage记录。在示例SQL和linq代码中,AnotherID的值仅为0,仅用于示例。

  • 对于每个ParsedMessage记录,我还需要NumberOfOccurences(表#2的字段)

  • 仅检索每个MessageTypeID的前(100)个ParsedMessage记录。因此,例如,如果ParsedMessages中有275条记录链接到AnotherID == 0,其中前150条记录具有MessageTypeID == 0,其余125条记录具有MessageTypeID == 1,我希望我的查询最终返回200条记录,带有MessageTypeID == 0的top(100)和带有MessageTypeID == 1的top(100)

经过大量的搜索,我发现我想做的简单SQL等同于此。我知道这存在于第一端,但是我试图在没有Union的情况下找到其他的东西,但是没有这样做(我的SQL知识不是那么好):

  

SELECT TOP(100)PM。*,   PML.NumberOfOccurences FROM   ParsedMessages PM INNER JOIN   ParsedMessageLinks PML ON   PM.ParsedMessageID =   PML.ParsedMessageID WHERE   PML.AnotherID = 0 AND PM.MessageTypeID   = 0 ORDER BY PM.ParsedMessageID DESC UNION ALL

     

SELECT TOP(100)PM。*,   PML.NumberOfOccurences FROM   ParsedMessages PM INNER JOIN   ParsedMessageLinks PML ON   PM.ParsedMessageID =   PML.ParsedMessageID WHERE   PML.AnotherID = 0 AND PM.MessageTypeID   = 1 PMDER.ParsedMessageID DESC UNION ALL订购

     

SELECT TOP(100)PM。*,   PML.NumberOfOccurences FROM   ParsedMessages PM INNER JOIN   ParsedMessageLinks PML ON   PM.ParsedMessageID =   PML.ParsedMessageID WHERE   PML.AnotherID = 0 AND PM.MessageTypeID   = 2订购PM.ParsedMessageID DESC

基本上,检索我需要的数据的唯一方法是在单个传递中执行3个sql查询,其中每个查询只有PM.MessageTypeID不同。

现在我想用linq-to-sql实现这个目标。谷歌搜索后,我发现我可以使用Linq Concat()方法重现SQL Union All。 以下是一些指向我认为可行的链接: http://blog.benhall.me.uk/2007/08/linq-to-sql-difference-between-concat.html

EF. How to union tables, sort rows, and get top entities?

我最终得到了这个例外: System.IndexOutOfRangeException:“索引超出了数组的范围。”

这是错误的代码:

IQueryable<MyObject> concatquery;
int[] allMessageTypeIDs = new int[] { 0, 1, 2 };
for (int mt = 0; mt < allMessageTypeIDs.Length; mt++)
{
    if (mt == 0)
    {
        concatquery = (from pm in db.ParsedMessages
                       join pml in db.ParsedMessageLinks on pm.ParsedMessageID equals pml.ParsedMessageID
                       where pml.AnotherID == 0 && pm.MessageTypeID == allMessageTypeIDs[mt]
                       orderby pm.ParsedMessageID descending
                       select new MyObject
                       {
                           NumberOfOccurences = pml.Occurrences,
                           ParsedMessage = pm
                       }).Take(100);
    }
    else
    {
        concatquery = concatquery.Concat(from pm in db.ParsedMessages
                                        join pml in db.ParsedMessageLinks on pm.ParsedMessageID equals pml.ParsedMessageID
                                        where pml.AnotherID == 0 && pm.MessageTypeID == allMessageTypeIDs[mt]
                                        orderby pm.ParsedMessageID descending
                                        select new MyObject
                                        {
                                            NumberOfOccurences = pml.Occurrences,
                                            ParsedMessage = pm
                                        }).Take(100);
    }
}
var results = concatquery.ToArray();

为简单起见,我已将int数组声明为allMessageTypeIDs。但要记住它所拥有的值可能不同,所以这就是我添加for循环的原因。也许在循环中使用Concat()是“非法的”,但我找不到关于此异常的任何相关信息。

MyObject类基本上包含一个int(NumberOfOccurences)和一个ParsedMessage数据库对象,没有别的。

有关导致异常的代码可能出错的任何建议吗?

由于 弗朗西斯

1 个答案:

答案 0 :(得分:2)

切勿在Linq查询中使用您正在循环的变量。它只是不起作用。您想要分配一个新的临时变量来代替使用。

IQueryable<MyObject> concatquery;
int[] allMessageTypeIDs = new int[] { 0, 1, 2 };
for (int mt = 0; mt < allMessageTypeIDs.Length; mt++)
{
    var myItem = allMessageTypeIDs[mt]; // <-- HERE!
    if (mt == 0)
    {
        concatquery = (from pm in db.ParsedMessages
                       join pml in db.ParsedMessageLinks on pm.ParsedMessageID equals pml.ParsedMessageID
                       where pml.AnotherID == 0 && pm.MessageTypeID == myItem
                       orderby pm.ParsedMessageID descending
                       select new MyObject
                       {
                           NumberOfOccurences = pml.Occurrences,
                           ParsedMessage = pm
                       }).Take(100);
    }
    else
    {
        concatquery = concatquery.Concat(from pm in db.ParsedMessages
                                        join pml in db.ParsedMessageLinks on pm.ParsedMessageID equals pml.ParsedMessageID
                                        where pml.AnotherID == 0 && pm.MessageTypeID == myItem
                                        orderby pm.ParsedMessageID descending
                                        select new MyObject
                                        {
                                            NumberOfOccurences = pml.Occurrences,
                                            ParsedMessage = pm
                                        }).Take(100);
    }
}
var results = concatquery.ToArray();