我正在使用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数据库对象,没有别的。
有关导致异常的代码可能出错的任何建议吗?
由于 弗朗西斯
答案 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();