Рекомендации по фильтрации данных и повторного использования кода с Onion Architecture - PullRequest
0 голосов
/ 08 июля 2011

Вот мои вопросы, а затем я дам вам справку по ним:

  • Я бы предпочел использовать Метод 2 в качестве дизайна моего приложения, поэтому есть ли способ предоставитьфильтрация, как в методе 1, без введения ссылок на некоммерческий код и без предоставления доступа к модели базы данных в проекте Core?

  • Как вы справляетесь с повторным использованием кода?Пространства имен для каждого объекта являются чем-то вроде Project.Core.Domain или Project.Core.Services, но если вам кажется странным делать пространство имен чем-то вроде CompanyName.Core.Domain, когда оно не хранится в этом проекте.В настоящее время я копирую файлы исходного кода и переименовываю пространства имен, чтобы справиться с этим, но мне интересно, есть ли организационный способ справиться с этим или что-то еще, о чем я не думал?

Используемые мной технологии:

  • ASP.NET MVC 3
  • Linq-to-SQL
  • StructureMap
  • Moq
  • MSTest

Метод 1:


Вот как я использовал для настройки своих веб-проектов: enter image description here

Проект Data будет содержать все репозитории и контексты данных Linq.В репозитории я бы возвратил коллекцию объектов из базы данных, используя IQueryable.

public IQueryable<Document> List()
{
    return from d in db.Documents
           select d;
}

Это позволило мне настроить фильтры, которые были статическими методами.Они также были сохранены в проекте данных.

public static IQueryable<Document> SortByFCDN(this IQueryable<Document> query)
{
    return from d in query
           orderby d.ID
           select d;
}

На сервисном уровне фильтр можно применять следующим образом.

public IPagedList<Document> ListByFCDN(int page, IConfiguration configuration)
{
    return repository.List().SortByFCDN().ToPagedList(page, configuration.PageSize, configuration.ShowRange);
}

Следовательно, хранилище должно предоставлять толькоМетод ListAll, который возвращает все элементы в виде объекта IQueryable, а затем уровень обслуживания определяет, как его отфильтровать, прежде чем возвращать подмножество данных.

Мне нравится этот подход, и он сделал мои репозитории чище, оставляя большую частькод в сервисах.

Метод 2


Вот как я сейчас настраиваю свои веб-проекты: enter image description here

Использование лукаАрхитектура:

  • Ядро: содержит модель бизнес-домена, все интерфейсы для приложения и реализации классов обслуживания.
  • Инфраструктура: содержит реализации репозитория, контексты данных Linq и классы отображениядля сопоставления модели базы данных Linq с бизнес-моделью.

Поскольку я отделяю свой бизнес-код от базы данных codНапример, я не хочу добавлять ссылки в проекте Core на такие вещи, как Linq, чтобы получить доступ к IQueryable.Итак, мне пришлось выполнить фильтрацию на уровне хранилища, сопоставить модель базы данных с моделью домена, а затем вернуть коллекцию объектов домена на уровень обслуживания.Это может добавить дополнительные методы в мои репозитории.

1 Ответ

0 голосов
/ 19 июля 2011

Вот что я в итоге сделал:

1) Создал объект перечисления фильтрации в проекте Core.

public enum FilterType
{
    SortFCDN
}

2) В классе обслуживания (также в рамках проекта Core)), сделайте что-то вроде:

    public IPagedList<Document> ListByFCDN(int page)
    {
        Dictionary<FilterType, object> filters = new Dictionary<FilterType, object>();

        filters.Add(FilterType.SortFCDN, "");

        return repository.List(page, filters);
    }

3) В репозитории (в рамках проекта Infrastructure):

    public IPagedList<Document> List(int page, Dictionary<FilterType, object> filters)
    {
        //Query all documents and map to the model.
        return (from d in db.DbDocuments
                select d).Filter(filters).Map(
                    page, 
                    configuration.Setting("DefaultPageSize", true).ToInt(), 
                    configuration.Setting("DefaultShowRange", true).ToInt());
    }

4) Создайте класс фильтров в проекте Infrastructure:

public static class DocumentFilters
{
    public static IQueryable<DbDocument> Filter(this IQueryable<DbDocument> source, Dictionary<FilterType, object> filters)
    {
        foreach (KeyValuePair<FilterType, object> item in filters)
        {
            switch (item.Key)
            {
                case FilterType.SortFCDN:
                    source = source.SortFCDN();
                    break;
            }
        }

        return source;
    }

    public static IQueryable<DbDocument> SortFCDN(this IQueryable<DbDocument> source)
    {
        return from d in source
               orderby d.ID
               select d;
    }
}

Служебный уровень (основной проект) может затем решить, какие фильтры применить, и передать эти фильтры в хранилище (проект инфраструктуры) до выполнения запроса.Можно применять несколько фильтров, если только один фильтр применяется к одному типу FilterType.

Словарь фильтров может содержать тип фильтра и любое значение / объект, которые необходимо передать в фильтр.Также легко можно добавлять новые фильтры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...