Есть ли способ использовать мультикарту Dapper с явными функциями для каждого типа?
Мы ищем следующие функциональные возможности при использовании многокарточной семантики для Dapper (Dapper-Dot-Net):
SqlMapper.Configure.ForTypeUseFunc<T>(Func<dynamic,T> func);
//example usage
Func<object,Foo> fooFunc = (dynamic o) =>
new Foo{
Name = o.Name,
Status = (StatusTypes)o.StatusID
};
SqlMapper.Configure.ForTypeUseFunc<Foo>(fooFunc);
cnn.Query<Foo,Bar,Foo>...
Поэтому, когда Dapper разделяет IDataReader для типа 'Foo', он передает все значения как динамические fooFunc
и, следовательно, сделал бы то же самое для "Бар". Передаваемый "динамический" объект будет представлять разделенные столбцы (и точно так же, как обычная мультикарта может иметь повторяющиеся имена столбцов).
Как мы можем достичь этого?
Фон
Мы широко используем Dapper в некоторых устаревших базах данных, но из-за большого количества старых шаблонов вынуждены использовать динамический вывод для сопоставления результатов с объектами (различные имена столбцов, вложенные объекты и т. Д.)
Реальность такова, что, хотя мы пишем ручное отображение, любые несоответствия между базой данных (которая находится вне нашего контроля) и нашим объектом четко и явно определены в Func. База данных, состоящая из 50 таблиц (которые я бы назвал средними), занимает всего пару часов, чтобы составить карту, и представляет собой ничтожную долю времени любого развития... полностью стоящее.
Это хорошая часть.
Часть, с которой мы боремся, заключается в том, что нам трудно получить хорошее повторное использование кода из наших функций, даже если они ведут себя отлично при использовании. В идеале у нас был бы какой-то способ использовать мультикарту Dapper, но назначить для каждого типа Func:
Я изучил ITypeMap и IMemberMap, и они, похоже, ориентированы на индивидуальное сопоставление для каждого поля. Мы действительно ищем пользовательское сопоставление для каждого типа (и мы будем обрабатывать назначения).
Я счастлив попытаться встроить это в Dapper сам (и внес незначительный вклад в прошлом), но хотел бы немного руководства.
Спасибо!
ОБНОВИТЬ
Я сейчас пытаюсь Query<dynamic,dynamic,Foo>
но это не расщепляется должным образом. Это могло бы работать для нас, если бы оно раскололось правильно. Мы могли бы эффективно подключить каждую динамику к нашему функционалу и вернуть наши строго типизированные объекты:
Query<dynamic,dynamic,Tuple<Foo,Bar>>((d1,d2)=>Tuple.Create(fooFunc(d1),barFunc(d2)));
1 ответ
Dapper достаточно подлый, чтобы позволить вам разделить на несколько dynamic
типы. Есть много закулисных реализаций, которые мы могли бы использовать для достижения желаемой цели. Ниже один.
Query<dynamic,dynamic,Tuple<Foo,Bar>>((d1,d2)=>Tuple.Create(fooFunc(d1),barFunc(d2)));
Замечательно. За кулисами вы можете хранить тип /func в любом удобном для вас месте (например, в словаре.
Проблема, с которой мы сейчас имеем дело, заключается в том, что к дублирующимся именам столбцов добавляются номера (например, AddressID, AddressID1), что делает операторы SELECT * не очень полезными.