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

时间:2013-10-25 16:34:43

标签: c# linq-to-sql data-binding

我试图允许将列表框数据绑定中的项目转移到内存中的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()调用。

1 个答案:

答案 0 :(得分:2)

你应该记住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();
}