Мое приложение читает из базы данных Sql Server или Oracle.
Большинство запросов очень просты, и в большинстве случаев нет разницы в семантике запросов.Я решил не использовать наборы данных, а непосредственно преобразовывать результаты в DTO:
SomeDto data = GetResult<SomeDto>("SELECT * FROM table");
В методе GetResult
я использую AutoMapper
с расширениями AutoMapper.Data
.Ниже приведено упрощенное содержание метода GetResult
.
public IEnumerable<T> GetResult(string query)
{
using(DbConnection db = GetConnection())
{
var command = db.CreateCommand()
command.CommandText = query;
return mapper.map<IDataReader, IEnumerable<T>>(dataReader);
}
}
Благодаря расширениям AutoMapper.Data я могу преобразовать устройство чтения данных непосредственно в DTO с помощью конфигурации автоматического устройства.
cfg.AddDataReaderMapping();
Проблема
База данных Oracle и Sql Server имеет одинаковую структуру, но есть некоторые несоответствия в типах столбцов.
Например, Oracle NUMBER(8)
интерпретируется как int
, а Sql Server NUMBER(8,0)
интерпретируется как decimal
, хотя это действительно всегда целое число (да, это должно быть int, но я не могуделать что-нибудь с этим).Если целевой тип в DTO не соответствует, генерируется исключение несоответствия типов.
public class SomeDto
{
//works fine with Oracle
//throws exception when using Sql Server
public int ID { get; set; }
}
Я не могу изменить типы базы данных, и я ожидаю, что появятся другие подобные несоответствия, поэтому я решил, что я сконфигурировал автопроизводитель.
Что-то вроде:
- , если свойство DTO имеет тип X, а значение, присвоенное ему, имеет определенный тип, используйте это явное преобразование.
Например
mapper.map<IDataReader, IEnumerable<T>>(dataReader, options => {
options.ConfigureMap()
//simple explicit cast, no loss of precision expected
.UseThisCastWhenMappingToDTO<decimal, int>(decimalInput => (int)decimalInput);
});
Вопрос
Можно ли сказать что-то вроде UseThisCastWhenMappingToDTO<TSource, TTarget>
с AutoMapper?
Потому что, похоже, это возможно, но я понятия не имею, как это сделать.Я не смог найти никакой документации или примеров того, как можно указать пользовательскую конфигурацию при сопоставлении IDataReader
с IEnumerable<T>
.