简体   繁体   English

根据另一个IQueryable的值对IQueryable进行排序

[英]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.NameSubjectSentDate排序的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 我现在能做的唯一方法是从数据库返回所有MessageFrom对象,并将它们手动组合成一个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? 有没有一种方法,而无需先返回完整的MessageFrom列表?

UPDATE 更新

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM