powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Вопрос архитектурного плана
12 сообщений из 12, страница 1 из 1
Вопрос архитектурного плана
    #36575515
Dim@sty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброе время суток коллеги.
Решил написать приложение с использованием шаблона DDD, но возникло несколько вопросов архитектурного характера.

Вот простенькая модель сущностей

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
class Profile:Entity<long>
{
        string Name{get;set;}
        IList<Modules> Modules{get;set;}
        IList<Resource> Resources{get;set;}

        public bool IsUrnContains(string urn)
        {
               foreach(Resource resource in Resources)
               {
                     if(resource.URN == urn) return true;
               }
               return false;
        }
}
class Resource : Entity<long>
{
        string URN{get;set;}
        string Description{get;set;}
}
class Module : Entity<long>
{
       string Name{get;set;}
       string Description{get;set;}
}


Весь CRUD этих сущностей я вынес в репозитории.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
interface IRepository<TEntity, TId> : IDisposable
{
       IList<EntityT> FindAll();
       EntityT GetById(Tid id);
       EntityT Save(EntityT entity);
       EntityT Update(EntityT entity);
       void Delete(EntityT entity);
}

interface IProfileRepository:IRepository<Profile,long>{}
interface IModuleRepository:IRepository<Module,long{}
interface IResourceRepository:IRepository<Resource,long>{}


Для работы с БД использую NHibernate, соответственно реализовал эти репозитории - <репозиторий>NH. Каждый репозиторий в конструкторе получает ISession. Для создания репозиториев я ввел интерфейc:

Код: plaintext
1.
2.
3.
4.
5.
6.
interface IRepositoryFactory
{
        IProfileRepository GetProfileRepository();
        IResourceRepository GetResourceRepository();
        IModuleRepository GetModuleRepository();
}

Реализовал RepositoryFactoryNH где конфигурируется NHibernate, открывается сессия и передается в репозитории. В коде я уже пользуюсь IRepositoryFactory

Теперь собственно вопросы.

1) Как использовать IRepositoryFactory так что бы при замене RepositoryFactoryNH на RepositoryFactoryEF не пришлось лазать по коду и менять new RepositoryFactoryNH на new RepositoryFactoryEF ?

2)Должны ли сущности знать о существовании IRepositoryFactory или о конкретном репозитории?

3)Например мне нужно сохранить модуль только в том случае если если Name != "Module1". Куда поместить этот код? В репозиторий? токда эта логика будет дублироваться в пакетах репозиториев.

В общем прошу совета. За ранее спасибо.


С/У DIM@STY
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36575964
Dmitry Sukhovilin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dim@sty,

1) Посмотрите GoF - AbstractFactory. http://www.dofactory.com/Patterns/PatternAbstract.aspx
Вам нужно добавть abstract factory и 2 concrete factories

2) Модель не должна знать о factory но должна знать о конкретном репозитории.

3) В домене.
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36576394
Dim@sty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dmitry Sukhovilin,

Спасибо за ответ. Я только начинаю щупать DDD поэтому возникают проблемы.

Получается объект должен знать, что его состояние куда то сохраняется? и в нем же делегировать вызовы репозиторию? т.е. что то типа

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
class Module
{      
      void Save()
      {
          if(Name!="Module1") repository.Save(this);
      }
}
?
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36576450
Dmitry Sukhovilin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dim@sty,

Не совсем, объект должен иметь признак или набор признаком указывающие можно ли его сохранять или нет. Например:
HasChanged, IsNew и т.д. в EF эти признаки прописаны в базовом классе.

В даннм случае модель показывает, что она валидна и может сохранится.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
public bool IsValid{
get
{
  return Name != "Module1";
}
}

...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36576456
Dmitry Sukhovilin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dim@styDmitry Sukhovilin,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
class Module
{      
      void Save()
      {
          if(Name!="Module1") repository.Save(this);
      }
}
?


Это очень похоже на active record :)
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36576679
Dim@sty
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dmitry Sukhovilin

Это очень похоже на active record :)

Так вот и я про то же. Зачем же тогда модели знать о конкретном репозитории?


автор
В даннм случае модель показывает, что она валидна и может сохранится.


Опять же надо где то проверить IsValid
Код: plaintext
1.
2.
if(module.IsValid) repository.Save(module)


Может быть в слое служб? Например


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
class ApplicationService
{
      protected virtual IRepositoryFactory GetRepositoryFactory()
     {
             return new RepositoryFactoryNH();
     }
}

class ModuleService : ApplicationService
{
      void SaveModule(Module module)
     {
             if(!module.IsValid) throw new NotValidException();
             
             this.GetReositoryFactory().GetModuleRepository().Save(module)
     }
}


А это уже получается transaction script.....

Чего то у меня вообще мозг взрывается. Буду благодарен за любые советы.
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36576721
Dmitry Sukhovilin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dim@styDmitry Sukhovilin

Это очень похоже на active record :)

Так вот и я про то же. Зачем же тогда модели знать о конкретном репозитории?


Репозиторий должен знать о модели, что бы вызврашять ее из источника наззных. Я не много опечатался. Сорри. :(
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36577098
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dim@sty...
Может быть в слое служб? Например
...

Именно в нем, родимом...
Dim@sty...
А это уже получается transaction script.....

А кто сказал, что это плохо?

Вообще, Repository - это довольно "низкоуровневый" слой, его задача - инкапсулировать доступ к сохраняемому состоянию модели (Domain Model), ниже него уже только Store (хошь БД, а хошь - массивы в памяти).

А вот то, что наворочено выше Repository - целиком на воображении архитектора/разработчика, можно и Active Record с BL внутри DM, а можно и Service Layer с отделенной BL и "тупой" DM (до уровня DTO/POCO).

З.Ы. и не надо такого "тяжеловесного" вытаскивания IModuleRepository в ModuleService: ... GetReositoryFactory().GetModuleRepository() .Save(module); ...
достаточно инжектировать IModuleRepository в конструкторе ModuleService:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
abstract class ApplicationService<T> where T: IRepository
{
      T Repository { get; private  set; }
      public ApplicationService(T r) { Repository = r; }
}

class ModuleService : ApplicationService<IModuleRepository>
{
      public ModuleService (IModuleRepository r) : base(r) {}
      // actions
      void SaveModule(Module module)
     {
             if(!IsValidModule(module)) throw new NotValidException();
             
             this.Repository.Save(module)
     }
      // validation rules
      bool IsValidModule(Module module)
     {
             return module.Name != "Module1";
     }
}
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36577152
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dmitry Sukhovilin...
Репозиторий должен знать о модели...
В общем случае - не обязательно...
(генерики придумали не вчера).

Вот такой репозиторий ничего не знает о модели, которую он возвращает (кроме того, что у нее есть свойство Key):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
public interface IKeyed<T>
{
    T Key { get; set; }
}

public class Repository<T,Tkey> where T: IKeyed<Tkey>
{
    private IQueryable<T> _queryable; 
    public Repository(IQueryable<T> source) 
    {
        _queryable = source; 
    }
    
    public IList<T> FindAll() // честно говоря, при наличии "нужной" реализации IQueryable этот метод - лишний...
    {
        return _queryable.ToList();
    }

    public T GetByKey(Tkey key)
    {
        return _queryable.FirstOrDefault<T>(e => e.Key == key);
    }
}
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36577394
Dmitry Sukhovilin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qu-quDmitry Sukhovilin...
Репозиторий должен знать о модели...
В общем случае - не обязательно...
(генерики придумали не вчера).

Так можно реализовать только CRUD, приходится расширять CRUD репозиторий специфичными для данного репозитория методами. И не всегда эти расширенные методы работают с <T>.
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36577397
Dmitry Sukhovilin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qu-quDim@sty...
Может быть в слое служб? Например
...

Именно в нем, родимом...
Dim@sty...
А это уже получается transaction script.....

А кто сказал, что это плохо?

Martin Fowler
...
Рейтинг: 0 / 0
Вопрос архитектурного плана
    #36577402
Dmitry Sukhovilin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qu-quDmitry Sukhovilin...
Репозиторий должен знать о модели...
В общем случае - не обязательно...
(генерики придумали не вчера).

Вот такой репозиторий ничего не знает о модели, которую он возвращает (кроме того, что у нее есть свойство Key):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
public interface IKeyed<T>
{
    T Key { get; set; }
}

public class Repository<T,Tkey> where T: IKeyed<Tkey>
{
    private IQueryable<T> _queryable; 
    public Repository(IQueryable<T> source) 
    {
        _queryable = source; 
    }
    
    public IList<T> FindAll() // честно говоря, при наличии "нужной" реализации IQueryable этот метод - лишний...
    {
        return _queryable.ToList();
    }

    public T GetByKey(Tkey key)
    {
        return _queryable.FirstOrDefault<T>(e => e.Key == key);
    }
}

Существует более высокая вероятность дублирования кода валидации в этом случае imho.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Вопрос архитектурного плана
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]