是否可以在内存中重新排序 LINQ IQueryable

本文关键字:排序 IQueryable LINQ 新排序 内存 是否 | 更新日期: 2023-09-27 18:36:51

我正在尝试允许重新处理绑定到内存中 linq 实体结果集的列表框中的项目。 实体记录的结构如下:

public class DisplayEntity
{
    public int IDPK { get; set; }
    public int OrderInt { get; set; }
    public string Name { get; set; }
}

它们按整数列加载和排序,形式为 荷载法和因子法:

IQueryable<DisplayEntity> entitylist = null;
private void WindowForm_Load(object sender, EventArgs e)
{
    entitylist = from e in dbcontext select e;
    RefreshList();
}
private void RefreshList()
{
    entitylist = entitylist.OrderBy(e => e.OrderInt); //order by
    dbcontext.Refresh(RefreshMode.KeepChanges, entitylist);
    listBoxEntities.DataSource = entitylist;
}

首次加载数据集时,它会正确排序,但后续的数据更改和 RefreshList() 调用不会对实体列表重新排序。

private void ChangeOrder(int argIDPK, int argNewPosition)
{
    DisplayEntity tempe = (from e in entitylist where e.IDPK == argIDPK select e).First();
    tempe.OrderInt = argNewPosition;
    RefreshList();
}

我相信我的代码的问题在于 OrderBy 不使用内存中的 linq 结果或数据绑定,因为通过类似于使用 ChangeOrder 方法更改内存中实体列表实体之一的名称确实会在 RefreshList() 调用后显示更改的名称。

是否可以在内存中重新排序 LINQ IQueryable

您应该

记住,entityList是一个查询 - 它不是内存中实体的简单列表,每次您"排序"它或搜索某个实体时,它都会通过数据库执行。同时,Linq to Sql 跟踪从数据库返回的对象。如果内存中存在具有相同 ID 的实体,则会将其重新用于新的查询结果。

所以,这是发生的事情:

private void WindowForm_Load(object sender, EventArgs e)
{
    entitylist = dbcontext.Entities; // SELECT * FROM Entities
    RefreshList();
}
private void ChangeOrder(int argIDPK, int argNewPosition)
{
    // SELECT TOP(1) * FROM Entities WHERE IDPK = @argIDPK
    // query is executed here
    DisplayEntity tempe = entitylist.First(e => e.IDPK == argIDPK);
    tempe.OrderInt = argNewPosition;
    RefreshList();
}
private void RefreshList()
{
    // SELECT * FROM Entities ORDER BY OrderInt
    entitylist = entitylist.OrderBy(e => e.OrderInt);
    dbcontext.Refresh(RefreshMode.KeepChanges, entitylist);
    // query is executed here
    listBoxEntities.DataSource = entitylist;
}

这里棘手的时刻是,实体从数据库中返回,按数据库中的 OrderInt 字段值排序(即原始排序)。但是,当这些查询结果映射到内存对象时,将使用具有更改值的实例。因此,您具有具有本地更改值的实体,这些值按数据库值顺序排序。

如何解决这个问题 - 只需在本地更改数据库值时更新它:

private void ChangeOrder(int argIDPK, int argNewPosition)
{
    DisplayEntity tempe = entitylist.First(e => e.IDPK == argIDPK);
    tempe.OrderInt = argNewPosition;
    dbcontext.SubmitChanges(); // here we update database
    RefreshList();
}

或者在此处使用内存中列表而不是IQueryable

List<DisplayEntity> entitylist = null;
private void WindowForm_Load(object sender, EventArgs e)
{
    // query is executed only here
    entitylist = dbcontext.Entities.OrderBy(e => e.OrderInt).ToList();
    RefreshList();
}
private void RefreshList()
{    
    listBoxEntities.DataSource = entitylist.OrderBy(e => e.OrderInt).ToList();
}
private void ChangeOrder(int argIDPK, int argNewPosition)
{
    DisplayEntity tempe = entitylist.First(e => e.IDPK == argIDPK);
    tempe.OrderInt = argNewPosition;
    RefreshList();
}