2017-08-14 160 views
0

我有一个DataGridView和DataGridView的DataSource是一个BindingList我从实体框架(V6)通过context.Person.Local.ToBindingList()。 当我将DataSource设置为此BindingList后,我放弃了上下文,因为我认为保持上下文开放将是不好的做法。因此,如果我想添加一个新行,我会点击“添加”按钮,随着BindingNavigator随我将“人员”对象数据源拖到我的Windows窗体时创建。 每次我点击“添加”按钮,我都会得到一个异常,告诉我已经处理了上下文。 使用DataGridView时,我是否需要始终保持上下文打开状态?哦,并且:DataSource可能会在运行时根据列表框项的选择而改变。另外,当上下文已经被处理并且我从DataGridView中编辑了一行时,我怎么能找出(经过多次更改后)哪一行发生了变化? 我试图做的:保持DbContext打开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中显示了一个人的正确工作,但除了从该职位先前选择的人。我尝试了Clear()条目,但是如果我这样做并且两次点击同一个人,那么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

为什么不在任何行被编辑或更改后执行此过程否则您需要检查所有datagr逐行查看idview查看其中哪些已更改 – hasan

+0

此答案可能会帮助您https://stackoverflow.com/a/11520100/8175473 – hasan

+0

@hsnbl我没有考虑这一点,因为我希望EF会为我自动执行此操作。但是只有当我保持上下文打开的时候,这个自动化才能工作:-( – AudioGuy

回答

0

虽然我尽量不保留的DbContext开放的很长一段时间,你不要”数据网格没有多少选择。我将网格的DataSource属性设置为IQueryable<T>,然后所有编辑,删除和添加由网格和上下文本身处理。只要您想保留更改,您只需拨打dbContext.SubmitChanges()即可。通过保存RowLeaveRowValidated事件,您可以保存每次用户离开一行。或者,您可以在关闭表格时保存。但也请确保在关闭表格时致电dbContext.Dispose()

要找出哪些行改变你可以查看由执行以下操作返回ChangeSet

var changes = dbContext.GetChangeSet(); 
dbContext.SubmitChanges(); 
+0

感谢@ jaredbaszler为您的答案。但是,这有点让我担心:如果我有一个使用DataGridView的软件,并且如果该软件使用它一个永久开放的窗口(也就是说它位于软件的主屏幕上),那么这个软件将会是'坏'的? – AudioGuy

+0

只要你在完成它的时候处理DBContext就不会被认为是坏的。 – jaredbaszler

0
  • 请确定您的物品是否为空。

  • 检查您的连接字符串。

而且,试试这个:

db.People.Add(item); 

相反的:

db.People.Attach(item); 
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(); 
} 
  • 编辑条目工作
  • 添加新条目作品
  • 删除条目工作