переопределение бриза BeforeSaveEntity()

У меня была точно такая же проблема, как обсуждалось в проблемах breezejs с пакетом сохранения и ответ объясняет это прекрасно.

У меня проблема в том, что мое приложение несколько велико, в нем более 20 объектов, которые мы модифицируем. Следовательно, если я переопределю BeforeSaveEntity() в моем контексте данных и добавлю туда всю бизнес-логику, это будет очень громоздко. У нас есть четкое разделение проблем, как я уже упоминал в следующем вопросе (обратите внимание на неполный заголовок): Хорошо ли использовать несколько

Так я могу сделать это более организованно? Я имею в виду обработку BeforeSaveEntity для связанных сущностей в одном репозитории и так далее?


person devC    schedule 28.01.2015    source источник


Ответы (1)


Конечно, вы можете разветвляться внутри своего метода BeforeSaveEntities, как показано в коде ответ, на который вы ссылались выше. Внутри каждого блока if вы можете создать вспомогательный класс или репозиторий для обработки каждого типа сущности.

Более основанный на предметной области подход состоял бы в том, чтобы иметь несколько подклассов EFContextProvider<MyDbContext>. У каждого будет свой собственный метод BeforeSaveEntities для обработки своих бизнес-правил домена:

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.

Вы можете создать соответствующий экземпляр ContextProvider в методах вашего контроллера:

[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);
}

... который вы вызываете из клиента, используя именованные сохранения:

    var saveOptions = new breeze.SaveOptions({ resourceName: 'SaveInventory' });
    return manager.saveChanges(null, saveOptions);
person Steve Schmitt    schedule 28.01.2015
comment
Спасибо, Стив. Еще одна проблема, которую я беспокою, заключается в том, что пользователь может отправить вредоносный пакет сохранения, включив объект типа, который не разрешен для сохранения, например объект поиска. В таком случае, как мы делаем валидацию? Я имею в виду, должны ли мы проверять все в пакете, рассматривая все объекты в контексте данных? - person devC; 28.01.2015
comment
Правильно — BeforeSaveEntities должен проверить типы в saveMap, чтобы убедиться, что клиент не отправляет ничего незаконного. Я обновил свой ответ, чтобы показать пример этого в файле AccountManagementContextProvider. Возможно, вам придется пойти глубже и убедиться, что текущий пользователь сохраняет только те отдельные сущности, которые ему разрешено сохранять. - person Steve Schmitt; 28.01.2015
comment
Спасибо, я думаю, это то, что мне нужно. - person devC; 29.01.2015
comment
Спасибо также @SteveSchmitt за отличный ответ. Мне было интересно, не могли бы вы рассказать о том, как добиться того, о чем вы упомянули в конце вашего последнего комментария, убедиться, что текущий пользователь сохраняет только те отдельные объекты, которые ему разрешено сохранять. Например, если у Account есть ApplicationUser Owner, это единственный пользователь, которому разрешено редактировать его. - person bcstrawn; 09.06.2016
comment
Если вы используете атрибут [Authorize] в методе веб-API, пользователь будет доступен. Затем вы можете передать пользователя в конструктор вашего поставщика контекста и применить бизнес-правила на основе пользователя. - person Steve Schmitt; 10.06.2016