C# 如何对数据库中未存储的字段进行排序

C# 如何对数据库中未存储的字段进行排序,c#,asp.net-mvc,linq,razor,C#,Asp.net Mvc,Linq,Razor,我有一个asp.net mvc站点,无法对模型中需要时计算的字段进行排序 private decimal _total = -1; public decimal Total { get { if (_total < 0) { _total = get_total(TableId); } return _tot

我有一个asp.net mvc站点,无法对模型中需要时计算的字段进行排序

    private decimal _total = -1;
    public decimal Total
    {
        get
        {
            if (_total < 0)
            {
                _total = get_total(TableId);
            }
            return _total;
        }
    }

    private decimal get_total(int id)
    {
       ....Many Calcs
    }
我发现了一些类似的问题,但我就是不知道该如何排序

还有我的控制器。为了清晰起见,我试着把它编辑下来

    public ActionResult Index(string sortOrder)
    {

        ViewBag.CurrentSort = sortOrder;
        ViewBag.Total = sortOrder == "total" ? "total_desc" : "total";

        var records = from u in db.Records.Include(t => t.User).Where(t => t.Active == true)
                     select u;

        switch (sortOrder)
        {
             case "total":
                records = db.Records.OrderBy(u => u.Total).Where(t => t.Active == true);
                break;
            case "rating_desc":
                records = db.Records.OrderByDescending(u => u.Total).Where(t => t.Active == true);
                break;
            default:
                records = db.Records.OrderBy(u => u.Title).Where(t => t.Active == true);
                break;
        }

        return View(records.ToList());
    }
在尝试按此属性排序之前,请尝试调用
ToList()
方法,因为这无法转换为
SQL
语句

//我假设当前您的查询是这样的
DbContext.SomeEntity.Where(…).OrderBy(e=>e.Total);
//调用.ToList()后,可以在内存中对数据进行排序(而不是在db中)
DbContext.SomeEntity.Where(…).ToList().OrderBy(e=>e.Total);
更新:
问题是,首先用此行声明
记录
变量:

var records = from u in db.Records.Include(t => t.User).Where(t => t.Active == true) select u;
因此,
记录
变量的类型将是
System.Linq.IQueryable
,这就是为什么在开关情况下“需要”使用
.AsQueryable()强制转换的原因

此外,初始值将始终在switch语句中被重写,因此完全没有必要像当前那样初始化它

你应该做什么:

public ActionResult Index(string sortOrder)
{
    /* ViewBag things */

    IEnumerable<Record> records =
        db
            .Records
            .Include(record => record.User)
            .Where(record => record.Active)
            .ToList(); // At this point read data from db into memory

    // Total property cannot be translated into an SQL statement.
    // That's why we call it on memory objects instead of DB entities.
    switch (sortOrder)
    {
        case "total":
            records = records.OrderBy(record => record.Total);
            break;

        case "rating_desc":
            records = records.OrderByDescending(record => record.Total);
            break;

        default:
            records = records.OrderBy(record => record.Title);
            break;
    }

    return View(records.ToList());
}
公共操作结果索引(字符串排序器)
{
/*取景袋*/
可数记录=
分贝
.记录
.Include(record=>record.User)
.Where(record=>record.Active)
.ToList();//此时,将数据从数据库读取到内存中
//Total属性无法转换为SQL语句。
//这就是为什么我们对内存对象而不是DB实体调用它。
开关(分拣机)
{
案例“总计”:
records=records.OrderBy(record=>record.Total);
打破
案例“评级描述”:
records=records.OrderByDescending(record=>record.Total);
打破
违约:
records=records.OrderBy(record=>record.Title);
打破
}
返回视图(records.ToList());
}

我需要将我的查询转换为IQueryable,因此这里是更新的开关:

switch (sortOrder)
{
     case "total":
        records = db.Records.Where(t => t.Active == true).AsQueryable().OrderBy(u => u.Total));
        break;
    case "rating_desc":
        records = db.Records.Where(t => t.Active == true).AsQueryable.OrderByDescending(u => u.Total).;
        break;
    default:
        records = db.Records.Where(t => t.Active == true).AsQueryable.OrderBy(u => u.Title).;
        break;
}

显示对数据进行排序的查询。不显示实际排序的代码,也不显示添加此
Total
属性的代码。从外观上看,我猜您是通过一个分部类将其添加到EF实体中的。更改查询后,我现在遇到以下错误:错误12无法隐式地将类型“System.Linq.iorderenumerable”转换为“System.Linq.IQueryable”。存在明确的转换(您是否缺少演员阵容?)有任何想法?在我的回答中添加了有关您转换问题的更新。感谢Gabor的更新。这样做的唯一真正好处是避免强制转换每个switch语句吗?我只是好奇,因为我希望很快实现延迟加载,我相信ienumerable不支持这一点,但我再次将其抛出——我只是在做同样的事情——我是c#的新手。将
记录的类型
变量显式设置为
ienumerable
的好处是我必须调用
ToList()
在对结果列表进行排序后,只需执行一次。如果我使用了
List
,那么我应该在每个switch语句中调用
ToList()
。但是:当我初始化
records
变量时,我必须调用
ToList()
,因为它会迭代resultset,从而导致查询被转换为SQL语句并执行。以便从数据库中读取数据并加载到内存中。此步骤需要能够按
Total
属性排序,因为它无法转换为SQL。此外,您可以在此处阅读有关
List
vs
IEnumerable
的延迟加载:添加了有关转换问题的我的答案的更新。你不需要像我更新的答案中描述的那样施法。
switch (sortOrder)
{
     case "total":
        records = db.Records.Where(t => t.Active == true).AsQueryable().OrderBy(u => u.Total));
        break;
    case "rating_desc":
        records = db.Records.Where(t => t.Active == true).AsQueryable.OrderByDescending(u => u.Total).;
        break;
    default:
        records = db.Records.Where(t => t.Active == true).AsQueryable.OrderBy(u => u.Title).;
        break;
}