[英]Entity Framework 6.1: CRUD on Child objects
我用來自存儲庫的對象列表填充數據網格,如下所示:
public static IEnumerable<Order> GetOrdersForDataGrid()
{
IEnumerable<Order> query;
using (RSDContext = new RSDContext())
{
query = context.Orders.Include(o=>o.OrderDetails).ToList();
}
return query;
}
當我要編輯訂單時,將選定的行傳遞到新窗口,如下所示:
OrderEditWindow orderEdit = new OrderEditWindow();
orderEdit.SelectedOrder = SelectedOrder;
orderEdit.ShowDialog();
在這里,我將窗口的DataContext設置為:
DataContext = SelectedOrder;
在此窗口中,我還有另一個數據網格,該數據網格綁定到Order
OrderDetails
集合屬性。 問題在於在OrderDetails
上的CRUD操作。 例如,在我像這樣添加新的orderDetail之后:
private void AddProductDetailButton_OnClick(object sender, RoutedEventArgs e)
{
if (!ValidateProductDetail())
return;
var _selectedProduct = ProductAutoCompleteBox.SelectedItem as Product;
var selectedProduct = ProductsRepository.GetProductById(_selectedProduct.ProductId);
OrderDetail orderDetail = new OrderDetail();
orderDetail.Price = selectedProduct.Price;
orderDetail.ProductCode = selectedProduct.Code;
orderDetail.ProductName = selectedProduct.Name;
orderDetail.Quantity = int.Parse(QuantityNumericUpDown.Value.ToString());
orderDetail.Um = selectedProduct.Um;
orderDetail.Total = selectedProduct.Price * int.Parse(QuantityNumericUpDown.Value.ToString());
orderDetail.Group = selectedProduct.Subgroup.Group.Name;
orderDetail.Subgroup = selectedProduct.Subgroup.Name;
orderDetail.SupplierName = selectedProduct.Supplier.Name;
//orderDetail.Order=SelectedOrder;
//orderDetail.OrderId = SelectedOrder.OrderId;
SelectedOrder.OrderDetails.Add(orderDetail);
ProductAutoCompleteBox.Text = string.Empty;
QuantityNumericUpDown.Value = 1;
ProductAutoCompleteBox.Focus();
}
然后從存儲庫調用update方法:
public static void UpdateOrder(Order order)
{
using (RSDContext context = new RSDContext())
{
context.Orders.Attach(order);
context.Entry(order).State = EntityState.Modified;
context.SaveChanges();
}
}
我收到有關OrderId的錯誤。 如果我手動設置導航屬性和ID,我不會收到錯誤,但是更改不會保存到數據庫中。
我的Order
模型如下所示:
public class Order : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Order()
{
_OrderDetails = new ObservableCollection<OrderDetail>();
_OrderDetails.CollectionChanged += _OrderDetails_CollectionChanged;
}
void _OrderDetails_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
AttachProductChangedEventHandler(e.NewItems.Cast<OrderDetail>());
if (e.OldItems != null)
CalcualteTotals();
}
[NotMapped]
public decimal CalculatedTotal
{
get
{
return OrderDetails.Sum(x => x.Total);
}
}
public int OrderId { get; set; }
private int _Number;
public int Number
{
get { return _Number; }
set
{
_Number = value;
NotifyPropertyChanged("Number");
}
}
private DateTime _Date;
public DateTime Date
{
get { return _Date; }
set
{
_Date = value;
NotifyPropertyChanged("Date");
}
}
private bool _Canceled;
public bool Canceled
{
get { return _Canceled; }
set
{
_Canceled = value;
NotifyPropertyChanged("Canceled");
}
}
private string _ClientName;
public string ClientName
{
get { return _ClientName; }
set
{
_ClientName = value;
NotifyPropertyChanged("ClientName");
}
}
private string _ClientPhone;
public string ClientPhone
{
get { return _ClientPhone; }
set
{
_ClientPhone = value;
NotifyPropertyChanged("ClientPhone");
}
}
private string _DeliveryAddress;
public string DeliveryAddress
{
get { return _DeliveryAddress; }
set
{
_DeliveryAddress = value;
NotifyPropertyChanged("DeliveryAddress");
}
}
private decimal _Transport;
public decimal Transport
{
get { return _Transport; }
set
{
_Transport = value;
NotifyPropertyChanged("Transport");
}
}
private decimal _Total;
public decimal Total
{
get { return _Total; }
set
{
_Total = value;
NotifyPropertyChanged("Total");
}
}
private ObservableCollection<OrderDetail> _OrderDetails;
public virtual ObservableCollection<OrderDetail> OrderDetails
{
//get { return _OrderDetails ?? (_OrderDetails = new ObservableCollection<OrderDetail>()); }
get
{
return _OrderDetails;
}
set
{
_OrderDetails = value;
NotifyPropertyChanged("OrderDetails");
}
}
private void AttachProductChangedEventHandler(IEnumerable<OrderDetail> orderDetails)
{
foreach (var p in orderDetails)
{
p.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
case "Quantity":
case "Price":
case "Total":
CalcualteTotals();
break;
}
};
}
CalcualteTotals();
}
public void CalcualteTotals()
{
NotifyPropertyChanged("CalculatedTotal");
}
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
我的OrderDetail模型如下所示:
public class OrderDetail : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int OrderDetailId { get; set; }
public int OrderId { get; set; }
public Order Order { get; set; }
private int _ProductCode;
public int ProductCode
{
get { return _ProductCode; }
set
{
_ProductCode = value;
NotifyPropertyChanged("ProductCode");
}
}
private string _ProductName;
public string ProductName
{
get { return _ProductName; }
set
{
_ProductName = value;
NotifyPropertyChanged("ProductName");
}
}
private string _Um;
public string Um
{
get { return _Um; }
set
{
_Um = value;
NotifyPropertyChanged("Um");
}
}
private decimal _Price;
public decimal Price
{
get { return _Price; }
set
{
_Price = value;
NotifyPropertyChanged("Price");
NotifyPropertyChanged("Total");
}
}
private int _Quantity;
public int Quantity
{
get { return _Quantity; }
set
{
_Quantity = value;
NotifyPropertyChanged("Quantity");
NotifyPropertyChanged("Total");
}
}
private string _SupplierName;
public string SupplierName
{
get { return _SupplierName; }
set
{
_SupplierName = value;
NotifyPropertyChanged("SupplierName");
}
}
private string _Subgroup;
public string Subgroup
{
get { return _Subgroup; }
set
{
_Subgroup = value;
NotifyPropertyChanged("Subgroup");
}
}
private string _Group;
public string Group
{
get { return _Group; }
set
{
_Group = value;
NotifyPropertyChanged("Group");
}
}
public decimal _Total;
public decimal Total
{
get { return Quantity * Price; }
set
{
_Total = value;
NotifyPropertyChanged("Total");
}
}
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
我真的在嘗試使用某種工作單元,但我不明白如何將CRUD應用到具有子集合的對象上並同時更新UI(通過在ObservableCollection
工作並使用Binding ClientPhone, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged
我的父窗口在輸入時會更新)
最終的工作解決方案:
using (RSDContext context = new RSDContext())
{
var details = order.OrderDetails;
order.OrderDetails = null;
List<int> OriginalOrderDetailsIds =
context.OrderDetails.Where(o => o.OrderId == order.OrderId).Select(o => o.OrderDetailId).ToList();
List<int> CurrentOrderDetailsIds = details.Select(o => o.OrderDetailId).ToList();
List<int> DeletedOrderDetailsIds = OriginalOrderDetailsIds.Except(CurrentOrderDetailsIds).ToList();
context.Entry(order).State = EntityState.Modified;
foreach (var deletedOrderDetailId in DeletedOrderDetailsIds)
{
context.Entry(context.OrderDetails.Single(o => o.OrderDetailId == deletedOrderDetailId)).State = EntityState.Deleted;
}
foreach (OrderDetail detail in details)
{
// Add.
if (detail.OrderDetailId == 0)
{
detail.OrderId = order.OrderId;
context.Entry(detail).State = EntityState.Added;
}
// Update.
else
{
context.Entry(detail).State = EntityState.Modified;
}
}
context.SaveChanges();
}
您可以通過這種方式添加和更新子項,但是不確定ui中已刪除的訂單詳細信息。 如果您不想從實體獲取訂單,則需要在OrderDetail中對已刪除的OrderDetail進行某種標記。
using (RSDContext context = new RSDContext())
{
var details = order.OrderDetails;
order.OrderDetails = null;
context.Entry(order).State = EntityState.Modified;
foreach (var detail in details)
{
if (detail.Id == 0)
{
// Adds.
detail.OrderId = order.Id;
context.Entry(detail).State = EntityState.Added;
}
else if (detail.IsDeleted)
// Adds new property called 'IsDeleted'
// and add [NotMapped] attribute
// then mark this property as true from the UI for deleted items.
{
// Deletes.
context.Entry(detail).State = EntityState.Deleted;
}
else
{
// Updates.
context.Entry(detail).State = EntityState.Modified;
}
}
order.OrderDetails = details;
context.SaveChanges();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.