如何通过除自己的属性之外的其他东西对集合进行排序?

时间:2017-06-16 19:01:19

标签: c# asp.net-mvc entity-framework linq

关于向ASP.NET MVC应用程序添加基本排序/过滤,我正在关注this tutorial

问题是,我实际上并不想按模型的属性排序,而是从模型的string属性派生int

下面的ExceptionModelClientIDPatientIDPhysicianID,它们链接到另一个DbSet中的条目。我需要按该条目的名称排序。

public ActionResult Index(string sortOrder)
{
    ViewBag.ClientSortParam = System.String.IsNullOrEmpty(sortOrder) ? "client_desc" : "";
    ViewBag.PatientSortParam = sortOrder == "Patient" ? "patient_desc" : "Patient"; // If sorting by Patient (ascending), flip to patient_desc, otherwise remain
    ViewBag.PhysicianSortParam = sortOrder == "Physician" ? "physician_desc" : "Physician";
    IQueryable<ExceptionModel> exceptions = from e in db.Exceptions
                                            select e; // Select all in table
    switch (sortOrder)
    {
        case "client_desc": // Default is Client ascending, at the bottom
            exceptions = exceptions.OrderByDescending(e => db.Clients.Find(e.ClientID).Name);
            break;

        case "Patient":
            exceptions = exceptions.OrderBy(e => db.Patients.Find(e.PatientID).Name);
            break;
        case "patient_desc":
            exceptions = exceptions.OrderByDescending(e => db.Patients.Find(e.PatientID).Name);
            break;

        case "Physician":
            exceptions = exceptions.OrderBy(e => db.Physicians.Find(e.PhysicianID).Name);
            break;
        case "physician_desc":
            exceptions = exceptions.OrderByDescending(e => db.Physicians.Find(e.PhysicianID).Name);
            break;

        default:
            exceptions = exceptions.OrderBy(e => db.Clients.Find(e.ClientID).Name);
            break;
    }

    return View(exceptions.ToList());
}

我当前的exceptions.OrderBy(e => db.Patients.Find(e.PatientID).Name)尝试会抛出此运行时异常:

  

System.ArgumentException:在类型'System.Data.Entity.DbSet`1 [EDB.Models.ClientModel]'上声明的方法'EDB.Models.ClientModel Find(System.Object [])'无法使用实例调用输入'System.Data.Entity.Core.Objects.ObjectQuery`1 [EDB.Models.ClientModel]'

编辑:

我被告知我应该使用实体导航属性。现在我只是有这样的事情:

public class ExceptionModel
{
    public int ID { get; set; }
    public int PatientID { get; set; }
    public int ClientID { get; set; }
    public int PhysicianID { get; set; }
}

public class PatientModel // Never need to go from Patient to Exception, so I typically access this with db.Patients.Find(exception.PatientID)
{
    public int ID { get; set; }
}

public class ClientModel
{
    public int ID { get; set; }
    public List<int> PhysicianIDs { get; set; } // One client has many physicians
    public string PhysicianStore { get { /* parse list to string */ } set { /* parse string to list and store in PhysicianIDs */ } }
}

public class PhysicianModel
{
    public int ID { get; set; }
    public int ClientID { get; set; } // Each physician maps to one client
}

我不明白我应该改变什么来解决这个问题。

2 个答案:

答案 0 :(得分:0)

Laurent Lequenne的评论是准确的。您正在使用实体。您尝试按客户端计算的值进行排序。实体无法将此计算转换为SQL Server语句,因此它会抛出异常。

关于它没有表现的评论也是如此。您可以使用ToList检索结果并继续处理,不会抛出任何异常,但是对于大型结果集会变得很难看;你想把那种处理推到一个细分市场。

答案 1 :(得分:0)

要访问相关数据,您应使用可翻译的联接。我认为你不需要Exceptions没有匹配的Clients等来排序,所以我使用了内连接。如果这样做,您可以使用左外连接。

public ActionResult Index(string sortOrder) {
    ViewBag.ClientSortParam = System.String.IsNullOrEmpty(sortOrder) ? "client_desc" : "";
    ViewBag.PatientSortParam = sortOrder == "Patient" ? "patient_desc" : "Patient"; // If sorting by Patient (ascending), flip to patient_desc, otherwise remain
    ViewBag.PhysicianSortParam = sortOrder == "Physician" ? "physician_desc" : "Physician";
    IQueryable<ExceptionModel> exceptions = db.Exceptions;

    switch (sortOrder) {
        case "client_desc": // Default is Client ascending, at the bottom
            exceptions = from e in exceptions join c in db.Clients on e.ClientID equals c.ClientID orderby c.Name descending select e;
            break;

        case "Patient":
            exceptions = from e in exceptions join p in db.Patients on e.PatientID equals p.PatientID orderby p.Name select e;
            break;
        case "patient_desc":
            exceptions = from e in exceptions join p in db.Patients on e.PatientID equals p.PatientID orderby p.Name descending select e;
            break;

        case "Physician":
            exceptions = from e in exceptions join p in db.Physicians on e.PhysicianID equals p.PhysicianID orderby p.Name select e;
            break;
        case "physician_desc":
            exceptions = from e in exceptions join p in db.Physicians on e.PhysicianID equals p.PhysicianID orderby p.Name descending select e;
            break;

        default:
            exceptions = from e in exceptions join c in db.Clients on e.ClientID equals c.ClientID orderby c.Name descending select e;
            break;
    }

    return View(exceptions.ToList());
}