【问题标题】:Entity Framework - (master detail) how to update Details which on a separate form from Master实体框架 - (主详细信息)如何更新与主信息不同的表单上的详细信息
【发布时间】:2016-05-31 13:53:07
【问题描述】:

我正在尝试为我的项目 Entity Framework Databinding with WinForms 执行此操作 但我没有使用单一形式,而是使用 2 种形式。

CategoryDataGridView显示在Form1上,然后Form1上有一个编辑按钮,它将加载具有ProductsDataGridView(所选类别的产品列表)的Form2和一个保存按钮以保存变化

我的 Form2 上有以下代码

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

我现在的问题是仅将产品的编辑保存到数据库。添加和删​​除不会保存到数据库中。

【问题讨论】:

  • 你确定你会看到Form1的变化吗?我假设它有自己的上下文和自己的缓存实体。

标签: c# winforms entity-framework


【解决方案1】:

你应该设置context.Products.Local作为绑定源的数据源,同时你设置context.Products.Local.ToList()

context.Products.Local 获得一个 ObservableCollection<Product>,它将与上下文保持同步,因此所有实体更改(添加/删除/编辑)都将通过上下文跟踪。
当您使用context.Products.Local.ToList() 时,您使用的是List<T>,它不会与上下文保持同步,并且不会跟踪添加/删除,当调用SaveChanges 时,您的添加和删除将不会被保存,而编辑将被保存.

DbSet<TEntity>.Local 得到一个ObservableCollection<T>,它代表所有的本地视图 此集合中添加、未更改和已修改的实体。这个局部视图 在上下文中添加或删除实体时将保持同步。 同样,添加到本地视图或从本地视图中删除的实体将 自动添加到上下文中或从上下文中删除。

代码:

你可以这样加载数据:

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;

您也不需要删除具有空类别的产品的那部分代码,因为您没有使用主-详细信息。这是一个可编辑的列表。

作为另一个旁注,不要忘记在关闭第二个表单后重新加载第一个表单中的数据。由于您在表单中使用不同的上下文,因此他们不知道其他上下文中的变化。

【讨论】:

  • 嗨,Reza,感谢您提供详细的答案.. 但是,在尝试将 productBindingSource.DataSource 设置为 Products.Local 的解决方案时,编辑和删除被保存到数据库,但添加没有保存到数据库并且还显示DataGridView Default Error Dialog 错误。以下是消息:DataGridView 中发生以下异常:System.IndexOutOfRangeException:索引 3 没有值。在 System.Windows.Forms.CurrencyManager.get_Item(Int32 index) 在 System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetError(Int32 rowIndex) 并显示 7 次。
  • 可能是因为您没有为新记录设置有效的CategoryId。不要在网格中显示CategoryId 列,而是在保存更改时,将所有产品的CategoryId 设置为SelectedCategoryId
  • 解决方法就是我说的。它已经过测试并且可以正常工作:)
  • 试过你的建议删除 categoryID 列,也删除了 CategoryName 列,但是我如何在保存时将所有产品的 Category 设置为 SelectedCategoryID 兄弟?
  • 如果您没有在模型中包含外键,请从 edmx 中删除模型并再次更新您的模型并包含外键。
【解决方案2】:

这不行,你必须删除产品而不是本地!

        foreach (var product in _context.Products.ToList())
        {
            if (product.Category == null)
            {
                _context.Products.Remove(product);
            }
        }
        this._context.SaveChanges();

如果您只想删除本地,则:

_context.Locals.Remove(local);

我不知道您对加载对象列表做了什么,但如果您尝试更改或删除 DbContext 中未找到的产品或本地实体,或者它是实体的副本,那么这不会工作。您需要原始检索到的实体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 2012-11-17
    • 2014-04-13
    相关资源
    最近更新 更多