internal static class ContextHelper
{
public static NorthwindEFEntities GetContext(IEntityWithRelationships entity)
{
return typeof(RelationshipManager).GetProperty("Context", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).
GetValue(entity.RelationshipManager, null) as NorthwindEFEntities;
}
}
partial class Order
{
private float _discount;
public float Discount
{
get { return _discount; }
set { _discount = value; }
}
private MMEntityCollection<Product> _products;
public MMEntityCollection<Product> Products
{
get
{
if (_products == null)
{
_products = new MMEntityCollection<Product>(ContextHelper.GetContext(this as IEntityWithRelationships),
() =>
{
var context = ContextHelper.GetContext(this as IEntityWithRelationships); // I did it again because context can change
if (!OrderDetails.IsLoaded)
OrderDetails.Load();
var products = new List<Product>();
foreach (OrderDetail od in OrderDetails)
{
if (!od.ProductReference.IsLoaded && (od.EntityState & (System.Data.EntityState.Added | System.Data.EntityState.Detached)) == 0)
od.ProductReference.Load();
for (int i = 0; i < od.Quantity; i++)
products.Add(od.Product);
}
return products;
}, (p) =>
{
var context = ContextHelper.GetContext(this as IEntityWithRelationships); // I did it again because context can change
if (!OrderDetails.IsLoaded)
OrderDetails.Load();
// We suppose one order can't be change by two different persons on same time
context.Refresh(RefreshMode.StoreWins, OrderDetails.Where(od => od.ProductID == p.ProductID));
var addOD = OrderDetails.FirstOrDefault(od => od.ProductID == p.ProductID);
if (addOD == null)
{
addOD = new OrderDetail { Order = this, Product = p, Quantity = 1, UnitPrice = p.UnitPrice.HasValue ? p.UnitPrice.Value : 0, Discount = Discount };
context.AddToOrderDetails(addOD);
}
else
addOD.Quantity++;
}, (p) =>
{
var context = ContextHelper.GetContext(this as IEntityWithRelationships); // I did it again because context can change
if (!OrderDetails.IsLoaded)
OrderDetails.Load();
// We suppose one order can't be change by two different persons on same time
context.Refresh(RefreshMode.StoreWins, OrderDetails.Where(od => od.ProductID == p.ProductID));
var removeOD = OrderDetails.FirstOrDefault(od => od.ProductID == p.ProductID);
if (removeOD == null)
return false;
else
{
removeOD.Quantity--;
if (removeOD.Quantity == 0)
context.DeleteObject(removeOD);
return true;
}
})
{
ClearMethod = (p) =>
{
var context = ContextHelper.GetContext(this as IEntityWithRelationships); // I did it again because context can change
if (!OrderDetails.IsLoaded)
OrderDetails.Load();
// We suppose one order can't be change by two different persons on same time
context.Refresh(RefreshMode.StoreWins, OrderDetails.Where(od => od.ProductID == p.ProductID));
var removeOD = OrderDetails.FirstOrDefault(od => od.ProductID == p.ProductID);
if (removeOD != null)
{
removeOD.Quantity = 0; // useful until saving changes
context.DeleteObject(removeOD);
}
}
};
}
return _products;
}
}
}
public class MMEntityCollection<TEntity> : ICollection<TEntity>, IEnumerable<TEntity>, IEnumerable, IListSource where TEntity : EntityObject
{
private Func<IEnumerable<TEntity>> _selectMethod;
private Action<TEntity> _addMethod;
private Func<TEntity, bool> _removeMethod;
private Action<TEntity> _clearMethod;
public MMEntityCollection(NorthwindEFEntities context, Func<IEnumerable<TEntity>> selectMethod, Action<TEntity> addMethod, Func<TEntity, bool> removeMethod)
{
if (selectMethod == null || addMethod == null || removeMethod == null)
throw new NullReferenceException();
_selectMethod = selectMethod;
_addMethod = addMethod;
_removeMethod = removeMethod;
}
public Action<TEntity> ClearMethod
{
get { return _clearMethod; }
set { _clearMethod = value; }
}
public void Add(TEntity item)
{
if (_addMethod != null)
_addMethod(item);
}
public void Clear()
{
foreach (var entity in this.Distinct())
Clear(entity);
}
public void Clear(TEntity item)
{
if (ClearMethod == null)
{
foreach (var entity in this.Where(i => i == item))
Remove(entity);
}
else
{
ClearMethod(item);
}
}
public bool Contains(TEntity item)
{
return Contains(item);
}
public void CopyTo(TEntity[] array, int arrayIndex)
{
CopyTo(array, arrayIndex);
}
public int Count
{
get { return Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(TEntity item)
{
if (_removeMethod != null)
return _removeMethod(item);
return false;
}
public IEnumerator<TEntity> GetEnumerator()
{
if (_selectMethod == null)
return null;
return _selectMethod().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
bool IListSource.ContainsListCollection
{
get { return false; }
}
IList IListSource.GetList()
{
if (_selectMethod == null)
return null;
return _selectMethod().ToList();
}
}