2016-07-14 5 views
0

Мое приложение имеет набор типов, реализующих IDataItem. Все они являются простыми типами «DTO», представляющими строки базы данных. Экземпляры создаются с использованием PetaPoco (микро ORM), запустив запрос SQL select к базе данных. Запрос выбора SQL специфичен для этого типа, а также зависит от номера версии приложения (предположим, что тип X имеет свойство Y, но до версии приложения N в базе данных нет соответствующего столбца - в этом случае запрос возвращает значение по умолчанию для тебя).Каждый тип, реализующий IDataItem, должен иметь связанную строку (SQL select qry), но доступ к ней до создания экземпляра типа

Характер приложения заключается в том, что существует много таких типов, и число будет расти в будущем. Я пытаюсь использовать generics на уровне доступа к данным, чтобы (i) минимизировать количество кода и (ii) заставлять будущих разработчиков создавать необходимые SQL-запросы по мере их создания.

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

  • имеет параметр типа T: IDataItem
  • возвращает IEnumerable Т
  • находит SQL запрос на выборку, связанный с T
  • запускает запрос к БД с помощью PetaPoco для создания списка T (его немного сложнее, чем это - есть также предложение dynamic where, но оставляя это для упрощения)

Моя задача - как получить SQL-запрос для параметра типа T до создания любых экземпляров T. В идеале я бы добавил метод к IDataItem, например. string SqlSelectFrom (int appVersion), но тогда мне нужен экземпляр для его вызова (если только для интерфейса может потребоваться статический член!). Лучшее, что я есть сейчас функция внутри слоя доступа к данным, как это (но это не реально выполнить мое требование, чтобы заставить разработчиков будущих типов реализовать запрос SQL):

private string GetSqlSelectFrom<T>(int appVersion) where T : IDataItem 
    { 
     if (typeof(T) == typeof(ProductDto)) 
      return "select ProductId, ProductCode from Product"; 

     if (typeof(T) == typeof(ColourDto)) 
      return "select ColourId, ColourCode from Colour"; 

     etc 

     throw new Exception("No SQL defined!"); 
    } 

Есть ли лучше шаблон для этого?

+0

Я могу представить себе два способа: (1) использование атрибута на классах DTO (2) с использованием вида реестра для типов DTO –

+0

Атрибуты не будут работать, так как запрос может отличаться в зависимости от версии приложения. Объясните подробнее о регистрации plz? – Laurence

ответ

1

Одним из способов является использование своего рода реестра для типов DTO:

public static class DtoRegistry 
{ 
    private static readonly Dictionary<Tuple<Type, int>, string> _sqlSelectByType = 
     new Dictionary<Tuple<Type, int>, string>(); 

    public static void RegisterDto<T>(int appVersion, string sqlSelect) where T : IDataItem 
    { 
     var key = new Tuple<Type, int>(typeof(T), appVersion); 
     _sqlSelectByType[key] = sqlSelect; 
    } 

    public static string GetSqlSelectFrom<T>(int appVersion) where T : IDataItem 
    { 
     var key = new Tuple<Type, int>(typeof(T), appVersion); 
     return _sqlSelectByType[key]; 
    } 
} 

и где-то в коде запуска приложения, все типы DTO должны быть зарегистрированы:

DtoRegistry.RegisterDto<ProductDto>(appVersion: 1, sqlSelect: "SELECT * FROM Products"); 
DtoRegistry.RegisterDto<ProductDto>(appVersion: 2, sqlSelect: "SELECT * FROM ProductsV2"); 

DtoRegistry.RegisterDto<ColourDto>(appVersion: 1, sqlSelect: "SELECT * FROM Colours"); 
DtoRegistry.RegisterDto<ColourDto>(appVersion: 2, sqlSelect: "SELECT * FROM ColoursV2"); 

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

+0

Звучит многообещающе, но sql-запрос не является константой. Это функция версии приложения. – Laurence

+0

А, ок. Я изменяю ответ. –

+0

Выполнено - теперь регистрация и поиск работы на appVersion –

 Смежные вопросы

  • Нет связанных вопросов^_^