Правильный способ сделать слой доступа к данным в модульной архитектуре? - PullRequest
0 голосов
/ 04 июня 2019

Я пишу модульное приложение на C #.У меня есть «ядро», которое разделено на слои, такие как: DAL, BLL и слой презентации.Итак, главный вопрос о моем DAL.

В моем приложении я хочу иметь возможность переключать базы данных.Из-за этого в моем DAL у меня есть 2 папки: Mysql и Postgresql.

У меня есть таблицы: Persons, Bands, Songs и т. Д. (15 таблиц).

Чтобы все эти таблицы были в однойместо, где я создал класс DBData.

public interface IDBData
{
   IPersonsDAO Persons {get;}
   IBandsDAO   Bands {get;}
   ...
}

public interface IBandsDAO
{
 ICollection<Band> GetBandsByPersonsInBand(int personsCount);
 ICollection<Band> GetAll();
}

Итак, для примера в DAL / Postgresql у меня есть

public class PostgresqlDbData : IDBData
{

 IConnectionFactory _connectionFactory

 //tables
 PostresqlPersonsDao _persons;
 PostresqlBandsDao _bands;


 PostgresqlDbData (IConnectionFactory connectionFactory)
 {
   _connectionFactory = _connectionFactory;
 }

  IPersonsDAO Persons get { return _persons ?? (_persons = new PostresqlPersonsDao (_connectionFactory)); }
  IBandsDAO   Bands get { return _bands?? (_bands = new PostresqlBandsDao (_connectionFactory)); }
  ...

}

Таким образом, я могу легко получить любой класс таблицы дао в своем коде, например:

IDBData dbData = new PostgresqlDbData (connectionFactory);

ICollection<Person> persons = dbData.Persons.GetSingers();
ICollection<Band> bands = dbData.Bands.GetBandsByPersonsInBand(7);
...

Почему я так сделал?

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

///Some class that uses my IdbData

public class OrderService
{
 IDBData _dbData
 ShopService(IDBData dbData)
 {
  _dbData = dbData;
 }

 public void OrderAlbum(string albumName, string bandName)
 {
  ...
   IAlbum album = _dbData.Albums.GetAlbum(albumName, bandName);
  ..
 }

 public void OtherMethod(string personName)
 {
  ...
   _dbData.Persons.GetPerson(personName);
  ..
 }

}

Как вы можете видеть в моем OrderService, я использую _dbData.И это внедряется в конструктор.

Да, возможно, это выглядит как Service Locator, но я не могу найти другой способ сделать его лучше.Если бы я этого не делал, мне нужно было бы внедрить каждый класс таблицы в методы.

Как я уже говорил, у меня есть модульное приложение.Таким образом, каждый модуль независим, но он знает о ядре.При инициализации модуля он получает экземпляр IDBData.

Например, у меня есть модуль "BandsRaitingModule".

Это главная проблема.

В IBandsDAO есть только 2 метода.Но мне нужен такой метод, как «GetBandsThatCreatedAt (int year)».IBandsDAO не имеет этот метод.В моем модуле я хочу сделать как

 // IBandsRaitingModuleData moduleDbData;

 ICollection<Band> bands = moduleDbData.Bands.GetBandsByPersonsInBand(7);
 ICollection<Band> bands = moduleDbData.Bands.GetBandsThatCreatedAt(7);

Так что я хочу иметь возможность использовать мой BandsRaitingModuleData в качестве IDBData и в то же время использовать другие методы.

Какой самый лучший способ достичь этого

1 Ответ

0 голосов
/ 06 июня 2019

Вам потребуется выполнить приведение к более узкому интерфейсу, чтобы получить более тонкие функции. Поэтому создайте интерфейс IBandsDAO с помощью более узких методов и сделайте так, чтобы он расширял ваш интерфейс IDBData. Это потребует отката к этому более узкому интерфейсу, но не заставит вас подключиться к конкретному интерфейсу провайдера и, таким образом, сохранит инкапсуляцию.

...