Проектирование взаимодействия с базой данных при соблюдении принципа единой ответственности - PullRequest
2 голосов
/ 21 января 2010

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

Производитель <== Зонды <==> ProbeSettings

Зонд имеет производителя. Зонд имеет 1 набор настроек. Доступ к связанным объектам осуществляется по всему приложению, и, честно говоря, текущая реализация - беспорядок.

В настоящее время вот общее представление о том, как реализованы средства связи и объекты:

public class Manufacturer
{
  public int ID; // Primary key, auto-incrementing on insert
  public string Name;
}

public class Probe
{
  public int ID; // Primary key, auto-incrementing on insert
  public int ManufacturerID;
  public string Name;
  public int Elements;
}

public class ProbeSettings
{
  public int ProbeID; // Primary key, since it is unique.
  public int RandomSetting;
}

// This class is a mess...
public static class Database
{
  public static string ConnectionString;

  public static void InsertManufacturer(Manufacturer manuf); // ID would be ignored here, since it's auto-incrementing.
  public static void InsertProbe(Probe probe); // Again, ID generally ignored.
  public static void InsertProbeSettings(ProbeSettings probeSet);

  public static Manufacturer[] GetAllManufacturer();
  public static Probe[] GetProbesFromManufacturer(int manufacturerID);
  public static Probe[] GetProbesFromManufacturer(Manufacturer manuf);
}

Я вижу здесь много проблем.

  1. Database делает слишком много.
  2. Эти объекты могут быть неизменными, когда действительно читаются, единственная проблема - после вставки, я не уверен, какой идентификатор им присвоен, а вставленный объект теперь устарел.
  3. Каждый раз, когда классу требуется получить информацию от Database, я должен добавить еще один метод Get для обработки определенного запроса.

Я действительно в недоумении от того, какая будет правильная реализация. Моя единственная реальная идея для улучшения - это какой-то базовый интерфейс для объектов базы данных, хотя он может помочь только для вставок ...

public interface IDatabaseObject
{
    void Insert(Database db);
    bool Delete(Database db);
}

Каков хороший способ реализовать это?

Ответы [ 2 ]

4 голосов
/ 21 января 2010

Что ж, лучшее решение для работы с БД при поддержании SRP (или любого другого типа нормального шаблона) - это использовать какой-либо ORM (например, NHibernate).

Это позволит вам работать с классами такими, какие они есть, вместо того, чтобы вручную подбрасывать их из / в БД.

Например, с NH ваши классы могут выглядеть так:

public class Manufacturer
{
  public string Name { ... }
  public IList<Probe> Probes { ... }
}

public class Probe
{
  public string Name { ... }
  public int Elements { ... }
  public ProbeSettings Settings { ... }
}

public class ProbeSettings
{
  public int RandomSetting;
}

Как видите, вам уже не нужно GetProbesFromManufacturer, поскольку вы можете просто перемещаться по коллекции в пределах производителя.

Кроме того, ORM будет управлять идентификаторами объектов и их сохранением. Таким образом, все, что вам нужно, это просто небольшое и фиксированное количество общих методов, таких как LoadById / LoadAll, которые хорошо вписываются в класс SRP, к которому относится доступ к данным. Также вам, вероятно, понадобится класс для каждого сложного и настраиваемого запроса к БД.

2 голосов
/ 21 января 2010

Звучит так, будто вы ищете ORM . Поскольку вы работаете в C #, я предполагаю, что у вас есть доступ к LinqToSQL как части .NET Framework. Linq может делать то, что вам нужно, даже если вы управляете базовыми операциями CRUD . Подобные проекты, также заслуживающие внимания, это Castle ActiveRecord и NHibernate.

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