【问题标题】:How do you sort by a property of an ICollection?如何按 ICollection 的属性排序?
【发布时间】:2014-12-27 02:22:16
【问题描述】:

我正在尝试找出模型参数的 ICollection 的显示或 LINQ 调用。具体来说,这是我的PurchReq 模型(采购申请):

public enum FiscalYear
{
    [Display(Name="2013")]
    LastYear,
    [Display(Name="2014")]
    ThisYear,
    [Display(Name="2015")]
    NextYear
}

public class PurchReq
{
    [Key]
    public int PurchReqID { get; set; }
    [Display(Name="Fiscal Year")]
    public FiscalYear FiscalYear { get; set; }
    //[ForeignKey("Project")]
    //public int ProjectID { get; set; }
    [Required]
    [Display(Name="Purchase Requisition Number")]
    public string PurchReqNum { get; set; }
    public string GLCode { get; set; }
    public string Fund { get; set; }
    public string Division { get; set; }
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    [Display(Name = "Purch Req Created")]
    public DateTime? DateCreated { get; set; }
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    [Display(Name = "Purch Req Submitted")]
    public DateTime? DateSubmitted { get; set; }

    //many projects to many purchReqs
    //public virtual Project Project { get; set; }
    public virtual ICollection<Project> Projects { get; set; }

    public PurchReq()
    {
        DateCreated = System.DateTime.Now;
        Projects = new HashSet<Project>();
    }

这是我的索引方法的 PurchReqController:

  var purchReqs = from p in db.PurchReqs
                        select p;

        if (!string.IsNullOrEmpty(searchString))
        {
            purchReqs = purchReqs.Where(s => s.Projects.Any(item => item.Vendor.VendorName.Contains(searchString)));
        }
        switch (sortOrder)
        {
            case "ProjectName_desc":;
                purchReqs = purchReqs.OrderByDescending(s => s.Projects);
                    //Any(item => item.Vendor.VendorName).ThenBy(n => n.Project.Description));
                break;
            case "PurchReqNum_desc":
                purchReqs = purchReqs.OrderByDescending(s => s.PurchReqNum);
                break;
            case "PurchReqNum_asc":
                purchReqs = purchReqs.OrderBy(s => s.PurchReqNum);
                break;
            case "FiscalYear_desc":
                purchReqs = purchReqs.OrderByDescending(s => s.FiscalYear);
                break;
            case "FiscalYear_asc":
                purchReqs = purchReqs.OrderBy(s => s.FiscalYear);
                break;
            case "GLCode_desc":
                purchReqs = purchReqs.OrderByDescending(s => s.GLCode);
                break;
            case "GLCode_asc":
                 purchReqs = purchReqs.OrderBy(s => s.GLCode);
                break;
            case "Fund_desc":
                purchReqs = purchReqs.OrderByDescending(s => s.Fund);
                break;
            case "Fund_asc":
                purchReqs = purchReqs.OrderBy(s => s.Fund);
                break;
            case "Division_desc":
                purchReqs = purchReqs.OrderByDescending(s => s.Division);
                break;
            case "Division_asc":
                purchReqs = purchReqs.OrderBy(s => s.Division);
                break;
            case "DateCreated_desc":
                purchReqs = purchReqs.OrderByDescending(s => s.DateCreated);
                break;
            case "DateCreated_asc":
                purchReqs = purchReqs.OrderBy(s => s.DateCreated);
                break;
            case "DateSubmitted_desc":
                purchReqs = purchReqs.OrderByDescending(s => s.DateSubmitted);
                break;
            case "DateSubmitted_asc":
                purchReqs = purchReqs.OrderBy(s => s.DateSubmitted);
                break;
            default:
                purchReqs = purchReqs.OrderBy(s => s.Projects);
                //purchReqs = purchReqs.OrderBy(s => s.Projects.Any(item => item.Vendor.VendorName)).ThenBy(n => n.Project.Description);
                break;
        }
        return View(purchReqs);

上面的控制器因为无法对 ICollection Projects 进行排序而抛出 DbSort 错误,这是可以理解的。我需要按 Projects.Project.Vendor.VendorName 对集合进行排序。这最初在 PurchReq 到 Project 是多对一但最近更改为多对多时有效。任何建议和帮助将不胜感激。

【问题讨论】:

  • 您得到的确切错误是什么?
  • 我收到项目集合的 DBSort 错误。我认为这是因为在启动排序时它现在不知道如何处理“项目对象”。

标签: c# linq icollection


【解决方案1】:

试试这个:

purchReqs = purchReqs.OrderBy(pr => pr.Projects.Count > 0 ? pr.Projects.First().Vendor.VendorName : "")
                     .ThenBy (pr => pr.Projects.Count > 0 ? pr.Projects.First().Description       : "");

这里我们使用First而不是Any;它为我们提供了一些合适的元素(当然,哪个都没有关系,但Any 只是给了我们一个布尔值,没有其他具体的东西可以让我们半随机地选择一个)。

我认为,在 C# 6 中,您可以使用 null-propagating 成员访问运算符来执行以下操作:

purchReqs = purchReqs.OrderBy(pr => pr.Projects.FirstOrDefault()?.Vendor?.VendorName)
                     .ThenBy (pr => pr.Projects.FirstOrDefault()?.Description);

无论哪种方式,两个排序调用都使用相同的结构,假设 Project 具有描述属性。

【讨论】:

  • The First 抛出了一个错误,并要求我改为执行 FirstOrDefault。然后我确实使用了 FirstOrDefault 但呈现的视图在该特定列中没有任何内容。
  • 这表明我的代码没有正确处理Projects 的结构。您可能需要对其进行调整,但基本上,如果您需要FirstOrDefault,它已经会给您提供不良数据,因此请检查以确保它不是一个空集合。嗯,可能会为此修改我的示例。
  • 嗯,很有趣。我会这样做,并再次感谢您的所有意见。感谢您花时间帮助我完成所有这些工作。
【解决方案2】:

我知道我在这个线程上已经很晚了,并且不是 MVC 方面的专家,但据我了解对集合排序,它通过取一个值并将其与同一列中的另一个值进行比较来工作。基本上,您需要从所需的集合中选择一个字段并将其提供给 OrderBy lambda。

尽可能简单,如下所示:

IQueryable purchReq = context.PurchReq.OrderBy(p => p.Projects.Select(pj => pj.Project).FirstOrDefault().Select(v => v.Vendor.VendorName).FirstOrDefault());

如果 Project 与 Vendor 也有一对一的关系,则替换

Select(v => v.Vendor.VendorName);

通过

Select(v => v.Vendor).FirstOrDefault().VendorName

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    相关资源
    最近更新 更多