1

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

4

1 回答 1

2

You should remember that entityList is a query - it's not a simple list of entities in memory, and it gets executed over database each time you are 'sorting' it or search some entity. At the same time Linq to Sql tracks objects which was returned from database. And if entity with same Id exists in memory, it is re-used for new queries results.

So, here is what happens:

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;
}

Tricky moment here that entities are returned from database ordered by OrderInt field value from database (i.e. original sorting). But when these query results are mapped to memory objects then instances with changed values are used. So, you have entities with locally changed values which are sorted in database values order.

How you can fix that - simply update database value when you are changing it locally:

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();
}

Or use in-memory list instead of IQueryable here:

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();
}
于 2013-10-25T16:41:28.510 回答