C# 实体框架-(主详细信息)如何更新与主详细信息分开的表单上的详细信息
我正试图为我的项目做这件事 但是我用的不是单一的形式,而是两种形式C# 实体框架-(主详细信息)如何更新与主详细信息分开的表单上的详细信息,c#,winforms,entity-framework,C#,Winforms,Entity Framework,我正试图为我的项目做这件事 但是我用的不是单一的形式,而是两种形式 CategoryDataGridView显示在Form1上,然后在Form1上有一个编辑按钮,该按钮将加载包含ProductsDataGridView(所选类别的产品列表)和一个保存按钮以保存更改的Form2 我的表格2上有以下代码 ProductContext _context = new ProductContext(); public int SeletedCategID { get; set; } private vo
CategoryDataGridView
显示在Form1
上,然后在Form1
上有一个编辑按钮,该按钮将加载包含ProductsDataGridView
(所选类别的产品列表)和一个保存按钮以保存更改的Form2
我的表格2上有以下代码
ProductContext _context = new ProductContext();
public int SeletedCategID { get; set; }
private void Form2_Load(object sender, EventArgs e)
{
_context.Products.Where(c => c.CategoryId == SeletedCategID).ToList();
productsBindingSource.DataSource = (_context.Products.Local).ToList();
}
private void SaveBtn_Click(object sender, EventArgs e)
{
this.Validate();
foreach (var product in _context.Products.Local.ToList())
{
if (product.Category == null)
{
_context.Products.Remove(product);
}
}
this._context.SaveChanges();
this.productsDataGridView.Refresh();
Form1 frm1 = (Form1)Application.OpenForms["Form1"];
frm1.Activate();
frm1.Refresh();
this.Dispose();
}
我现在的问题是,只有对产品的编辑保存到数据库中。添加和删除未保存到数据库。这无法工作,您必须删除产品,而不是本地
foreach (var product in _context.Products.ToList())
{
if (product.Category == null)
{
_context.Products.Remove(product);
}
}
this._context.SaveChanges();
如果只想删除本地文件,则:
_context.Locals.Remove(local);
我不知道您对加载对象列表做了什么,但是如果您试图更改或删除产品或在DbContext中找不到的本地实体,或者它是实体的副本,那么这将不起作用。您需要原始检索实体。您应该将
context.Products.Local
设置为绑定源的数据源,同时设置context.Products.Local.ToList()
context.Products.Local
获取一个ObservableCollection
,它将与上下文保持同步,因此所有实体的更改(添加/删除/编辑)都将按上下文进行跟踪。当您使用
context.Products.Local.ToList()
时,您使用的是一个列表
,该列表不会与上下文保持同步,添加/删除不会被跟踪,调用SaveChanges
时,您的添加和删除不会被保存,而编辑将被保存
获取表示所有对象的本地视图的ObservableCollection
在此集合中添加、更改和修改实体。这是本地的观点
将在从上下文中添加或删除实体时保持同步。
同样,添加到本地视图或从本地视图中删除的实体也将
自动添加到上下文或从上下文中删除
代码:
您可以通过以下方式加载数据:
context.Products.Where(x => x.CategoryId == SelectedCategoryId).ToList();
this.productBindingSource.DataSource = context.Products.Local;
this.Validate();
this.productBindingSource.EndEdit();
context.Products.Local
.Where(x => x.CategoryId == 0)
.ToList().ForEach(x =>
{
x.CategoryId = SelectedCategoryId;
});
context.SaveChanges();
this.DialogResult = DialogResult.OK;
您可以通过以下方式保存数据:
context.Products.Where(x => x.CategoryId == SelectedCategoryId).ToList();
this.productBindingSource.DataSource = context.Products.Local;
this.Validate();
this.productBindingSource.EndEdit();
context.Products.Local
.Where(x => x.CategoryId == 0)
.ToList().ForEach(x =>
{
x.CategoryId = SelectedCategoryId;
});
context.SaveChanges();
this.DialogResult = DialogResult.OK;
您也不需要删除具有空类别的产品的代码部分,因为您不使用master detail。这是一个可编辑的列表
另一方面,在关闭第二个表单之后,不要忘记在第一个表单中重新加载数据。由于您在表单中使用了不同的上下文,因此他们不知道其他上下文中的更改。您确定在
表单1
中会看到任何更改吗?我假设它有自己的上下文和自己的缓存实体。嗨,雷扎,谢谢你的详细回答。。但是,在尝试将productBindingSource.DataSource
设置为Products.Local
时,编辑和删除会保存到DB,但添加未保存到DB,并且还会显示一个DataGridView默认错误对话框
错误。下面是消息:DataGridView中发生以下异常:System.IndexOutOfRangeException:索引3没有值。在System.Windows.Forms.CurrencyManager.get_项(Int32索引)在System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetError(Int32 rowIndex)中显示7次。可能是因为您没有为新记录设置有效的类别ID
。不要在网格中显示CategoryId
列,而是在保存更改时,将所有产品的CategoryId
设置为SelectedCategoryId
。解决方案就是我说的。它经过测试并正常工作:)尝试了您的建议以删除categoryID列,也删除了CategoryName列,但如何在保存bro时将所有产品的类别设置为SelectedCategoryID?如果您未在模型中包含外键,请从edmx中删除模型,然后再次更新模型并包含外键。