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