【问题标题】:linq-to-sql Concat() throwing a System.IndexOutofRangeExceptionlinq-to-sql Concat() 抛出 System.IndexOutofRangeException
【发布时间】:2011-03-15 09:28:41
【问题描述】:

我正在使用 linq-to-sql Concat() 处理异常

我有 2 张桌子。 第一个表 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 知识不是很好):

选择 TOP(100) PM.*, PML.NumberOfOccurences 来自 ParsedMessages PM INNER JOIN ParsedMessageLinks PML ON PM.ParsedMessageID = PML.ParsedMessageID WHERE PML.AnotherID = 0 和 PM.MessageTypeID = 0 ORDER BY PM.ParsedMessageID DESC UNION ALL

选择 TOP(100) PM.*, PML.NumberOfOccurences 来自 ParsedMessages PM INNER JOIN ParsedMessageLinks PML ON PM.ParsedMessageID = PML.ParsedMessageID WHERE PML.AnotherID = 0 和 PM.MessageTypeID = 1 ORDER BY PM.ParsedMessageID DESC UNION ALL

选择 TOP(100) PM.*, PML.NumberOfOccurences 来自 ParsedMessages PM INNER JOIN ParsedMessageLinks PML ON PM.ParsedMessageID = PML.ParsedMessageID WHERE PML.AnotherID = 0 和 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 数据库对象,仅此而已。

关于我的代码可能有什么问题导致异常的任何建议?

谢谢 弗朗西斯

【问题讨论】:

    标签: c# linq-to-sql


    【解决方案1】:

    切勿在 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();
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多