I was having the exact same problem as discussed in breezejs issues with the save bundle and the answer explains it great.
The problem I have is - my application is somewhat large, having about 20+ entities that we modify. Hence if I override the BeforeSaveEntity() within my datacontext and add all the business logic there it would be very cumbersome. We do have a clear separation of concerns as I have mentioned in the following question (mind the half-completed title): Is it a good practice to use multuple
So is there anyway I can do this in a more organized manner? I mean handling the BeforeSaveEntity for related entities in one single repository and likewise?
Of course you can branch inside your BeforeSaveEntities
method, as shown in the code of the answer you linked to above. Inside each if
block, you could instantiate a helper class or repository to handle each entity type.
A more domain-based approach would be to have multiple subclasses of EFContextProvider<MyDbContext>
. Each one would have its own BeforeSaveEntities
method to handle its own domain business rules:
public class AccountManagementContextProvider : EFContextProvider<MyDbContext>
{
Type[] allowedTypes = new Type[] { typeof(Account), typeof(AccountAddress) };
protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap)
{
var illegalTypes = saveMap.Keys.Except(allowedTypes);
if (illegalTypes.Any())
{
throw new ArgumentException("Attempt to save illegal entities");
}
// account management stuff...
}
}
// in a separate file...
public class InventoryContextProvider : EFContextProvider<MyDbContext>
{
protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap)
{
// inventory stuff...
}
}
// etc.
You can instantiate the appropriate ContextProvider instance in your controller methods:
[HttpPost]
public SaveResult SaveAccount(JObject saveBundle)
{
var context = new AccountManagementContextProvider();
return context.SaveChanges(saveBundle);
}
[HttpPost]
public SaveResult SaveInventory(JObject saveBundle)
{
var context = new InventoryContextProvider();
return context.SaveChanges(saveBundle);
}
... which you call from the client using named saves:
var saveOptions = new breeze.SaveOptions({ resourceName: 'SaveInventory' });
return manager.saveChanges(null, saveOptions);