根据另一个IQueryable的值排序IQueryable

时间:2015-09-02 11:30:37

标签: c# linq linq-to-sql iqueryable

我有两个从Linq返回到SQL的IQueryables,我想要一个接一个地排序。基本上,这就是我所拥有的

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; }
}

我想返回按MessageFrom.NameSubject

排序的10个SentDate个对象的列表

我现在唯一可以做到这一点的方法是从数据库中返回所有MessageFrom个对象,并手动将它们组合到元对象中,如下所示

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();
}

有没有办法在不先返回MessageFrom的完整列表的情况下执行此操作?

更新

这里有一个更好的解释我想用franken代码做什么(这不是伪代码,不是真正的代码)

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);
}

这里的细微差别在于,第二个示例仅选择了10个消息对象,其中第一个示例必须选择所有消息对象才能按名称排序。

从技术上讲,我的第二个例子中的代码应该可以工作(我还没有尝试过)但是我想知道是否有一种更优雅的方法呢?

1 个答案:

答案 0 :(得分:1)

您可以像这样直接投射到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();