我有一个DataGridView,而DataGridView的DataSource是我通过context.Person.Local.ToBindingList()从实体框架(V6)获得的BindingList。 在我将DataSource设置为此BindingList之后,我处理了上下文,因为我读到保持上下文打开将是不好的做法。
所以,如果我想添加一个新行,我会点击我将“people”对象数据源拖到我的Windows窗体时创建的BindingNavigator附带的“添加”按钮。 每次我点击“添加”按钮,我都会得到一个异常,告诉我上下文已被处理掉。 使用DataGridView时是否需要始终打开上下文?哦和:DataSource可能会在运行时更改,具体取决于ListBox项的选择。
此外,当已经处理了上下文并且我从DataGridView编辑了一行时,我怎么能找到(在多次更改之后)哪一行发生了变化? 我试着这样做:
foreach(DataGridViewRow row in peopleDataGridView.Rows)
{
People item = (People)row.DataBoundItem;
if (item != null)
{
db.People.Attach(item);
}
}
db.SaveChanges();
...但SaveChanges()无法识别任何更改。但是,如果我强制每个附加项目处于“已修改”状态,则它会起作用。但我不想将100个项目更改为“已修改”,如果只有一个实际修改过。
有什么想法吗?
编辑1 哦,好吧,所以我改变了我的代码以保持上下文一直打开(或者至少只要表单显示)。 现在,我遇到了一个不同的问题(人们可能有很多工作):
private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
People p = (People)listBox1.SelectedItem;
if(p != null)
{
//jobBindingSource.Clear(); this caused another error at runtime...
db.Entry(p).Collection(b => b.Job).Load();
jobBindingSource.DataSource = db.Job.Local.ToBindingList();
}
}
绑定到此jobBindingSource实例的DataGridView显示一个人的正确作业,但另外显示以前所选人员的作业。我试图清除()条目,但如果我这样做并点击同一个人两次,datagridview开始有时根本不显示任何条目。一种奇怪的行为。 我现在做错了什么?
编辑2 好的......我自己找到了解决方案。但我拒绝接受这是正确的方法:
private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
People p = (People)listBox1.SelectedItem;
if(p != null)
{
db.Dispose();
db = new PeopleJobsEntities();
db.People.Attach(p);
db.Entry(p).Collection(person => person.Job).Load();
jobBindingSource.DataSource = db.Job.Local.ToBindingList();
}
}
只有我处理上下文并重新打开它,整个过程才有效。原因是如果我清除本地缓存(db.Job.Local),即使我使用Load()方法,它的条目也不会再次重新加载。有没有办法强制重新加载实体?
答案 0 :(得分:0)
请确保您的商品不是空。
检查您的连接字符串。
并试试这个:
db.People.Add(item);
而不是:
db.People.Attach(item);
答案 1 :(得分:0)
虽然我尽量不让DBContext保持打开很长一段时间,但是对于datagrids你没有太多选择。我将网格的DataSource
属性设置为IQueryable<T>
,然后所有编辑,删除和添加都由网格和上下文本身处理。只要您想要保留更改,就必须致电dbContext.SubmitChanges()
。通过保存RowLeave
或RowValidated
事件,您可以在用户每次离开行时保存。或者您可以在关闭表单时保存。但是也要确保在关闭表单时调用dbContext.Dispose()
。
要找出哪些行发生了变化,您可以通过执行以下操作查看返回的ChangeSet
:
var changes = dbContext.GetChangeSet();
dbContext.SubmitChanges();
答案 2 :(得分:0)
好的,感谢@jaredbaszler,我想出了一个适合我的解决方案。 我决定让DbContext一直保持活着。为了清除本地缓存,我在循环中分离了内部的每个实体。我认为这是一种非常令人作呕的方式。 必须是更好的方式......
这就是我所拥有的:
PeopleJobsEntities db;
public FormTest()
{
InitializeComponent();
db = new PeopleJobsEntities();
db.Database.Log = Console.Write;
db.People.Load();
List<People> peoplelist = db.People.Local.ToList();
listBox1.DataSource = peoplelist;
}
private void FormTest_FormClosing(object sender, FormClosingEventArgs e)
{
if (db != null)
db.Dispose();
}
private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
People p = (People)listBox1.SelectedItem;
if(p != null)
{
List<Job> oldlist = db.Job.Local.ToList();
foreach (Job j in oldlist)
{
db.Entry(j).State = EntityState.Detached;
}
db.Entry(p).Collection(b => b.Job).Load();
jobBindingSource.DataSource = db.Job.Local.ToBindingList();
}
}
private void jobBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
foreach(DataGridViewRow row in jobDataGridView.Rows)
{
if(row != null && row.DataBoundItem != null)
{
Job j = (Job)row.DataBoundItem;
if(db.Entry(j).State == EntityState.Added)
{
if(j.People.Count == 0)
{
People people = (People)listBox1.SelectedItem;
if (people != null)
j.People.Add(people);
}
}
}
}
db.SaveChanges();
}