- string nsvid="";
- string nsit="";
- string type="";
- string nzav="";
- string ninv="";
- string lim="";
- string tochnost="";
- string where="";
- System.DateTime dtp = System.DateTime.Today;
- Int64 pov=0;
- System.DateTime dtn = System.DateTime.Today;
- string texsos="";
- for (Int64 i = 0; i <>
- {
- if (!bdt[int.Parse(i.ToString())].Is___п_пNull())
- pp = long.Parse(bdt[int.Parse(i.ToString())].___п_п.ToString());
- if (!bdt[int.Parse(i.ToString())].Is___свид_Null())
- nsvid = bdt[int.Parse(i.ToString())].___свид_;
- if (!bdt[int.Parse(i.ToString())].IsНаименование_СИТNull())
- nsit = bdt[int.Parse(i.ToString())].Наименование_СИТ;
- if (!bdt[int.Parse(i.ToString())].IsТипNull())
- type = bdt[int.Parse(i.ToString())].Тип;
- if (!bdt[int.Parse(i.ToString())].Is_Заводской__Null())
- nzav = bdt[int.Parse(i.ToString())]._Заводской__;
- if (!bdt[int.Parse(i.ToString())].Is_Инвентарный___Null())
- ninv = bdt[int.Parse(i.ToString())]._Инвентарный___;
- if (!bdt[int.Parse(i.ToString())].IsПредел_измеренийNull())
- lim = bdt[int.Parse(i.ToString())].Предел_измерений;
- if (!bdt[int.Parse(i.ToString())].Is_Класс__разряд__ц_д___погрешностьNull())
- tochnost = bdt[int.Parse(i.ToString())]._Класс__разряд__ц_д___погрешность;
- if (!bdt[int.Parse(i.ToString())].IsВладелецNull())
- where = bdt[int.Parse(i.ToString())].Владелец;
- if (!bdt[int.Parse(i.ToString())].IsДата_поверкиNull())
- dtp = bdt[int.Parse(i.ToString())].Дата_поверки;
- if (!bdt[int.Parse(i.ToString())].IsПериодичность_поверкиNull())
- pov = long.Parse(bdt[int.Parse(i.ToString())].Периодичность_поверки.ToString());
- if (!bdt[int.Parse(i.ToString())].IsДата_следующей_поверкиNull())
- dtn = bdt[int.Parse(i.ToString())].Дата_следующей_поверки;
- if (!bdt[int.Parse(i.ToString())].Is_Тех_состояниеNull())
- texsos = bdt[int.Parse(i.ToString())]._Тех_состояние;
- pdt.AddPriborRow(i+1, nsvid, nsit, type, nzav, ninv, lim, tochnost, where, dtp, pov, dtn, tochnost);
- }
- priborTableAdapter.Update(pdt);
- pdt.AcceptChanges();
Достаточно беглого взгляда на этот код чтобы понять - реализация метода неоптимальна.
Мы наблюдаем большое количество операторов ветвления, что является признаком плохого тона и должно наталкивать на размышления об улучшении этого кода.
Поэтому, для иллюстрации я на коленке набросал более лаконичный подход, который можно повторно использовать.
1. Делаем универсальный конвертер данных:
- public static class ConvertUtils
- {
- public static object ToType(object originalValue, Type targetType)
- {
- if (targetType == typeof(string))
- {
- return originalValue.ToString();
- }
- if (targetType == typeof(int))
- {
- return int.Parse(originalValue.ToString());
- }
- throw new Exception(
- string.Format(
- "Type {0} is not expected.",
- originalValue.GetType().FullName));
- }
- }
Если есть необходимость можно расширить метод до ToType(object originalValue, Type originalType, Type targetType)
2. Заводим "словарик" для преобразования данных:
- var migrateDictionary = new SortedDictionary<string, type="">()
- {
- { "___п_п", typeof(long) },
- { "___свид_", typeof(string) },
- { "Наименование_СИТ", typeof(string) },
- };
Можно расширить словарик до такого вида:
Ключ = Имя исходного поля + его тип
Значение = Имя целевого поля + его тип
3. И непосредственно реализация метода по переносу данных. Ни зависит ни от чего, разве что от ADO.NET, а именно типов DataRow, DataTable, DataSet :)
- // Объекты DataRow естественно реально существуют :)
- DataRow sourceDataRow = null;
- DataRow targetDataRow = null;
- foreach (var migrateInfo in migrateDictionary)
- {
- var columnName = migrateInfo.Key;
- var targetType = migrateInfo.Value;
- var sourceValue = sourceDataRow[columnName];
- targetDataRow[columnName] = ConvertUtils.ToType(sourceValue, targetType);
- }
Итого задача сводится только к заполнению словарей, которые описывают алгоритм миграции. Т.е. по сути метод на вход ожидает предельно простые структуры данных, а реализация самого метода пишется один раз для миграции разных типов данных из разных таблиц.
Надеюсь что идея понятна. Не сочтите меня за велосипедостроителя. Я знаю что подобных примеров масса в интернете, и просто хочу донести эту мысль до тех, кто читает этот блог :)
2 комментария:
ИМХО идея со словариком, нарушает и без того нестрогую енкапсуляцию данных рекорда... Ну или переносит проверку названия колонки в рантайм, а в оригинальном коде это было бы компил тайм...
Второе, это NullReferenceException на originalValue.ToString();. По крайней мере оригинальный код это хендлил.
Хотя вобщемто сложно не согласиться что новый код намого лакончиней и понятней. Я бы наверное разве что реализацию ConvertUtils заменл бы с ифов на хештейбл.
Dictionary[Type, Function[object, object]]() converters = new Dictionary[Type, Function[object, object]]();
converters.Add(typeof(Int32), o => o == null ? String.Empty : Int32.Parse(o.ToString()));
А мож и не заменил бы... Фик его знает, с ифами пойму лучше читаеться...
> ИМХО идея со словариком, нарушает и без того нестрогую енкапсуляцию данных рекорда... Ну или переносит проверку названия колонки в рантайм, а в оригинальном коде это было бы компил тайм...
Полностью согласен. Однако в некоторых случаях стоит осознанно идти на компромисс. К тому же никто не запрещает заполнить словарик названиями колонок не в виде строковых литералов, а получить из непосредственно из объектной модели DataTable - использовать типизированный DataColumn.
> Второе, это NullReferenceException на originalValue.ToString();. По крайней мере оригинальный код это хендлил.
Повторюсь, моей целью было показать идею ухода от повторяющихся условных операторов. Я не пытался написать код со всеми проверками и, тем более, не проводил его отладку.
> Хотя вобщемто сложно не согласиться что новый код намого лакончиней и понятней. Я бы наверное разве что реализацию ConvertUtils заменл бы с ифов на хештейбл.
Да, действительно. Идея довольно неплохая. Нужно будет при случае попробовать поиграться с этим подходом.
Спасибо за комментарии.
Отправить комментарий