Если вы создаете DataTable
из SQL-запроса, рассматривали ли вы просто использование Dapper вместо этого?
Затем, вместо создания SqlCommand
с SqlParameters
, а также DataTable
и a DataAdapter
и так далее и далее, которые вы затем должны кропотливо преобразовать в класс, вы просто определяете класс, делаете имена столбцов запроса совпадают с именами полей, а параметры легко связаны по имени. У вас уже определен класс TankReading
, так что это будет действительно просто!
using Dapper;
// Below can be SqlConnection cast to DatabaseConnection, too.
DatabaseConnection connection = // whatever
IEnumerable<TankReading> tankReadings = connection.Query<TankReading>(
"SELECT * from TankReading WHERE Value = @value",
new { value = "tank1" } // note how `value` maps to `@value`
);
return tankReadings;
Теперь разве это не круто? Dapper очень оптимизирован и даст вам почти эквивалентную производительность при чтении напрямую с DataAdapter
.
Если в вашем классе вообще есть какая-либо логика или он неизменен или не имеет конструктора без параметров, то вам, вероятно, нужен класс DbTankReading
(как чистый объект POCO / Plain Old Class):
// internal because it should only be used in the data source project and not elsewhere
internal sealed class DbTankReading {
int TankReadingsID { get; set; }
DateTime? ReadingDateTime { get; set; }
int ReadingFeet { get; set; }
int ReadingInches { get; set; }
string MaterialNumber { get; set; }
string EnteredBy { get; set; }
decimal ReadingPounds { get; set; }
int MaterialID { get; set; }
bool Submitted { get; set; }
}
Вы бы использовали это так:
IEnumerable<TankReading> tankReadings = connection
.Query<DbTankReading>(
"SELECT * from TankReading WHERE Value = @value",
new { value = "tank1" } // note how `value` maps to `@value`
)
.Select(tr => new TankReading(
tr.TankReadingsID,
tr.ReadingDateTime,
tr.ReadingFeet,
tr.ReadingInches,
tr.MaterialNumber,
tr.EnteredBy,
tr.ReadingPounds,
tr.MaterialID,
tr.Submitted
});
Несмотря на работу по отображению, это все еще менее болезненно, чем метод таблицы данных. Это также позволяет вам выполнять какую-то логику, хотя, если логика представляет собой нечто большее, чем простое прямое отображение, я бы поместил логику в отдельный класс TankReadingMapper
.