是否可以在内存中重新排序 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() 调用后显示更改的名称。
您应该
记住,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();
}