[英]Ordering IQueryable based on values of another IQueryable
I've got two IQueryables returned from Linq to SQL and I want to sort one by the other. 我有两个从Linq返回到SQL的IQueryable,我想彼此排序。 Essentially, this is what I have 本质上,这就是我所拥有的
public class From
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Message
{
public int FromID { get; set; }
public string Subject { get; set; }
public DateTime SentDate { get; set; }
}
public class MetaMsg
{
public string FromName { get; set; }
public string Subject { get; set; }
public DateTime SentDate { get; set; }
}
I want to return a list of 10 Message
objects sorted by either From.Name
, Subject
or SentDate
我想返回由From.Name
, Subject
或SentDate
排序的10个Message
对象的列表
The only way I can do this right now is to return all Message
and From
objects from the database and manually combine them in to a meta object, like so 我现在能做的唯一方法是从数据库返回所有Message
和From
对象,并将它们手动组合成一个meta对象,如下所示
List<MetaMsg> list = new List<MetaMsg>();
var froms = db.From.Where(//etc).ToList();
var messages = db.Message.Where(//bla bla).ToList();
foreach(Message m in messages)
{
MetaMsg mm = new MetaMsg {
Subject = m.Subject,
SentDate = m.SentDate
FromName = froms.Where(f = f.ID == m.FromID).FirstOrDefault().Name
};
list.Add(mm);
}
if(//sort by subject)
{
list = list.OrderBy(x => x.Subject).Take(10).ToList();
}
else if(//sort by date)
{
list = list.OrderBy(x => x.SentDate).Take(10).ToList();
}
else
{
list = list.OrderBy(x => x.FromName).Take(10).ToList();
}
Is there a way to do this without returning a full list of Message
and From
first? 有没有一种方法,而无需先返回完整的Message
和From
列表?
Here's a better explanation of what I want to do in franken-code (that's not quite pseudo-code, not quite real-code) 这是我想用弗兰肯代码做的更好的解释(那不是伪代码,不是真正的代码)
List<MetaMsg> list = new List<MetaMsg>();
// get a list of 'From's, ordered by name
var froms = db.From.Where(//etc).OrderBy(x => x.Name);
var messages = null;
if(//sort by subject)
{
// order by subject and take 10
messages = db.Messages.OrderBy(x => x.Subject).Take(10).ToList();
}
else if(//sort by date)
{
// order by date and take 10
messages = db.Messages.OrderBy(x => x.Subject).Take(10).ToList();
}
else // sort by from Name...
{
// try and select 10 successive messages which have the fromID
// of our first (sorted) from on the list
int i = 0;
while(messages.Count < 10)
{
// if i is greater than the number of items in from, stop!
if(i > from.Count)
break;
messages += db.Messages.Where(x => x.FromID == from[i].ID).Take(10).ToList();
// if we don't quite make 10, keep going with the next id
i++;
}
}
// now create our list of froms.
foreach(Message m in messages)
{
MetaMsg mm = new MetaMsg {
Subject = m.Subject,
SentDate = m.SentDate
FromName = froms.Where(f = f.ID == m.FromID).FirstOrDefault().Name
};
list.Add(mm);
}
The subtle difference here is that this second example only ever selects 10 message objects, where as the first example has to select all of them in order to sort by from name. 此处的细微差别是,第二个示例仅选择10个消息对象,而第一个示例必须选择所有消息对象以便按名称进行排序。
Technically the code in my second example should work (I haven't tried it) but I'm wondering if there's a more elegant way of doing this? 从技术上讲,我第二个示例中的代码应该可以工作(我还没有尝试过),但是我想知道是否有更优雅的方法?
You can directly project to MetaMsg
like this: 您可以像这样直接投射到MetaMsg
:
var result = (from m in db.Messages
let fromName = (from f in db.From
where m.FromId == f.ID
select f.Name).FirstOrDefault()
/* If you have navigation properties setup, you may be able to do this */
let fromName = m.From.Name
orderby fromName
select new MetaMsg
{
Subject = m.Subject,
SentDate = m.SentDate,
FromName = fromName,
}).Take(10).ToList();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.