【问题标题】:Update one row using entity framework c#使用实体框架c#更新一行
【发布时间】:2020-08-20 07:51:27
【问题描述】:

我正在使用 C# 和实体框架开发 Windows 窗体应用程序。我把客户购买的所有产品都放在了 DGVNewOrder 中。对于 DGVNewOrder 中的每个产品,我想为每个售出的产品更新(按名称)库存数量。这是我尝试过的代码:'''

Product pro = new Product(); 

for (int i = 0; i < DGVNewOrder.RowCount - 1; i++)
{
    string Soled_Product_name = DGVNewOrder.Rows[i].Cells[0].Value.ToString();
    pro = db.Products.Where(d => d.Name == Soled_Product_name ).FirstOrDefault();
    int y = Convert.ToInt32(pro.QteInStock); // QteInStock befor selling 
    int x = Convert.ToInt32(DGVNewOrder.Rows[i].Cells[2].Value); // the sold quantity 
    pro.QteInStock = y - x;  //  The remaining quantity after the sale
    db.Entry(pro).State = EntityState.Modified;
    db.SaveChanges();
 }

这里的问题是数量没有发生更新,但是所有产品的名称都更改为与 DGVNewOrder 中出现的第一个产品相同的名称 我也试过这个

string Soled_Product_name = DGVNewOrder.Rows[i].Cells[0].Value.ToString();
          
Product c = (from w in db.Products
              where w.Name == Soled_Product_name
             select w).First();

int y = Convert.ToInt32(pro.QteInStock);
int x = Convert.ToInt32(DGVNewOrder.Rows[i].Cells[2].Value);
c.QteInStock = y - x;

db.Entry(pro).State = EntityState.Modified;
db.SaveChanges();

但给出相同的结果

【问题讨论】:

  • 尽量不要在循环之前创建pro对象并在pro = db.Products之前使用var,不确定这是否有帮助,但只是尝试一下
  • 我在代码中看不到任何可能导致这种情况发生的内容。也许问题是由代码的其他部分引起的。您是否在其他任何地方更改加载的产品?如果您能提供minimal reproducible example 会更好,以便我们帮助您发现问题。
  • 不要修改 EF 的内部状态(db.Entry(pro).state 行)。 EF 很清楚哪些属性已被更改,而无需您告诉它。
  • 您是否在数据库表的所有产品中看到相同的名称?或在您的 DataGridView 中?贴出的代码不足以重现问题小伙伴。
  • 同样的结果@Sowmyadhar Gourishetty @ Neil

标签: c# winforms entity-framework-5


【解决方案1】:

当您有一个显示集合元素的控件时,例如 DataGridView、ListView,直接编辑控件中的项目通常不是一个好主意。原因之一是您需要主动从控件中获取更改的项目。如果控件的显示发生变化,例如列的顺序发生变化,或者DataGridView中的行顺序发生变化,你必须主动找出发生了什么变化。

为此使用 DataBinding 更容易。将需要显示的项目放在BindingList&lt;T&gt;中,并将其分配给DataGridView.DataSource

DataGridViewColum.DataPropertyName 包含应在列中显示的&lt;T&gt; 的属性名称。每当操作员编辑一个值并接受它时,您都会收到有关您的 BindingList 已更改的通知。您不必再阅读DataGridView,您会自动知道在BindingList 中更新了完整的DataGridView。甚至添加或删除的行都在 BindingList 中

例子:

class OrderLine
{
    public int Id {get; set;}           // primary key of the OrderLine
    public int ProductId {get; set;}    // foreign key to the Product in this OrderLine
    public string ProductDescription {get; set;}
    public decimal ProductPrice {get; set;}
    public int NrOfItems {get; set;}
    public decimal TotalPrice => this.ProductPrice * this.NrOfItems;
}

您需要一个显示 ProductId / ProductDescription / ProductPrice / NrOfItems / TotalPrice 的 DataGridView。

Operatos 可以在 DataGridView 中添加新的 OrderLines,或者删除 OrderLines。他们无法更改 ProductId / ProductDescription / ProductPrice,但他们可以更改 NrOfItems。

DataGridView dgv = new DataGridView();

// Add columns. This is some tedious work, usually it is best to let visual studio designer
// do this
dgv.Columns.Add(new DataGridViewColumn()
{
     Name = "columnProductId",
     DataProperty = nameof(OrderLine.ProductId),
     ReadOnly = true;
     ...
}

你所有的专栏等等。

现在用一些初始项目填充您的 datagridview:

IList<OrderLine> initialOrderLines = ...
var actualOrderLines = new BindingList<OrderLine(initialOrderLines);
dgv.DataSource = actualOrderLines;

如果您没有初始订单行,请使用默认构造函数

然后,您的所有列都填充了实际的OrderLines。在编辑期间,此集合会自动更新。如果操作员添加新 Line,它会自动使用默认 OrderLine 初始化,或者如果您愿意,您可以在订阅事件 BindingList.OnAddingNew 时提供 OrderLine。

最后,操作员完成所有更改后,按下按钮:

void OnButtonReady_Clicked(object sender, ...)
{
    // you can be certain the the BindingList is up-to-date
    // you don't have to fetch the items from the DataGridView anymore.
    this.UpdateStock(this.actualOrderLines);
}

private void UpdateStock(IEnumerable<OrderLine> actualOrderLines)
{
     foreach (OrderLine orderLine in actualOrderLines)
     {
         // TODO: update the stock
     }
}

好消息是:如果更改了 Columns 的顺序,或者对 Rows 进行了排序,那么这对您的实际OrderLines 没有影响。如果将来您决定添加或删除列:没问题,您只知道您的信息在实际的OrderLines 中,谁在乎它如何显示给操作员,或者他如何编辑信息。

最后一件好事:如果您想通过简单的鼠标单击标题对列进行排序,请考虑Nuget Package BindingListView

BindingListView&lt;T&gt;代替BindingList&lt;T&gt;

var initialOrderLines = ...
BindingListView<OrderLine> actualOrderLines = new BindingListView<OrderLine>(initialOrderLines);
this.dgv.DataSource = actualOrderLines;

还有宾果游戏:每当您单击标题时,项目按列属性按升序或降序排列。即使是字形(显示排序顺序的小箭头)也能正确显示。

【讨论】:

  • 您已经为我的问题投入了一些时间,因为您是专家,并且在这里教了我很多东西。:@Harald Coppoolse
猜你喜欢
  • 2011-12-10
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
  • 1970-01-01
  • 2018-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多