简体   繁体   中英

C#, Entity Framework, How to Update(delete, add, edit) multiple rows at same time?

Sometimes, we would like to change order details by adding, removing, and editing orders by customer's request or depends on stock quantity.

So now want get some list and update including remove, edit, add rows, then save on database

What's the best efficiently way as C#, EntityFramework?

public class OrderDetail
{
  public int Id { get; set; }
  public int OrderId {get; set; }
  public int Qty{ get; set; }
  public string ItemName { get; set; }
}

/// Dummy db, OrderDetail Table
{
 {1, 1000, 24,"A"},
 {2, 1000, 12,"B"}
}


public void Update()
{
  using(var db = new xxEntities())
  {
    // Get All orders, OrderId==1000, total 2rows
    List<OrderDetails> list = db.OrderDetails.Where(x=> x.OrderId==1000).ToList();
    
    // remove some row or rows
    var temp1 = list.First(x=> x.Id==1);
    list.Remove(temp);

    // edit some row or rows
    var temp2 = list.First(x=> x.Id==2);
    temp2.Qty=100;
    
    // add some row or rows
    list.Add(new OrderDetail{ Id=3, OrderId=1000, Qty=2, ItemName="C"});
    list.Add(new OrderDetail{ Id=4, OrderId=1000, Qty=2, ItemName="D"});

    // Apply all changes
   db.SaveChanges();
  }
}


Additional Question

public void UpdateOrder(int orderId, List<OrderDetail> newOrders)
{
  var result = db.OrderDetails.Where(x=>x.OrderId==orderId).ToList();
  result = newOrders;
 
 // it does not work
 //db.OrderDetails.Update(result);

 db.OrderDetails.RemoveRange(result);
 db.OrderDetails.AddRange(newOrders);

 db.SaveChange();
}

is it right approach to update multiple rows?

As mentioned in another answer... EF will create individual statements for each of the changes that are detected (ie, updates, inserts, deletes) and submit them inside a single transaction. Gets the job done but is potentially very "chatty". Benefit is that you don't need to worry about the details of how it's getting done. Pretty easy to just modify the data object and call SaveChanges.

If you can consider not using EF for updates such as this... one way we do this kind of update is by creating a System.Data.DataTable and using that as a table-valued parameter into a stored procedure (if your datastore supports it).

Meta-code:

var dt = new DataTable();
var newRow = dt.NewRow();
newRow["column1"] = newdata; 
dt.Rows.Add(newRow);

Then just use dt as your input parameter and let the stored proc determine the insert/update/delete operations.

There is no "most efficient" way outside of making all changes then calling SaveChanges. upon which Ef will issue a lot of SQL Statements (one per operation).

There is most efficient way because there is no way to change the way Ef works and there is exactly one way Ef does its updates. They do NOT happen at the same time. Period. They happen in one transaction, one after the other, when you call SaveChanges.

If you want to Add / Remove / Update rows from your tables in Entity Framework, you have to Add / Remove / Update the items in your DbSet , not in fetched data.

using (var dbContext = new OrderContext())
{
    // Add one Order
    Order orderToAdd = new Order
    {
        // fill required properties; don't fill primary key
    }

    var addedOrder = dbContext.Orders.Add(orderToAdd);
    // note: addedOrder has no Id yet.

    // Add several Orders
    IEnumerable<Order> orders = ...
    dbContext.Orders.AddRange(orders);

    dbContext.SaveChanges();
    // now they've got their id:
    Debug.Assert(addedOrder.Id != 0);
    Debug.Assert(orders.All(order => order.Id != 0);
}

To Remove, you'll first have to fetch the complete Order

int orderIdToDelete = ...
using (var dbContext = new OrderContext())
{
    Order orderToDelete = dbContext.Orders.Find(orderIdToDelete);
    dbContext.Orders.Remove(orderToDelete);

    var ordersToDelete = dbContext.Orders
        .Where(order => order.Date.Year < 2000)
        .ToList();
    dbContext.Orders.RemoveRange(ordersToDelete);

    // the orders are not deleted yet.
    dbContext.SaveChanges();
}

To Update, you first have to get the value:

int orderIdToUpdate = ...
Order orderToUpdate = dbContext.Orders.Find(orderIdToUpdate);
orderToUpdate.Date = DateTime.Today;

var today = Datetime.Today;
var dateLimit = today.AddDays(-28);
var nonPaidOrders = dbContext.Orders
    .Where(order => !order.Paid && order.Date < dateLimit)
    .ToList();
foreach (var order in nonPaidOrders)
{
    this.SendReminder(order);
    order.ReminderDate = today;
}
dbContext.SaveChanges();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM