Сложное отображение из SQL Reader в объект

1

Мне нужно сопоставить результат хранимой процедуры с сложным объектом:

Допустим, моя хранимая процедура возвращает столбцы A, B, C, D, E, F

У меня есть класс, скажем:

class ABC{
    public int A;
    public string B;
    public int C;

    public virtual ICollection<DEF> DEFObj;
}

и класс DEF:

class DEF{
     int value;
     string comment;
}

Итак, здесь мне нужно взять значения столбца D, E, F и сохранить их в ICollection<DEF> в виде списка.

Какой был бы лучший способ сделать это, мог бы Automapper быть хорошим местом для начала или есть что-то еще?

PS: Мои данные находятся в объекте SQL Reader.

  • 0
    ORM (объектно-реляционный картограф, такой как NHibernate) будет работать лучше всего, если у вас есть время для его реализации и если ваше приложение позволяет это. Automapper лучше подходит для отображения типизированных моделей из одной в другую, но, вероятно, его можно использовать в этом сценарии. Вы также можете написать свою собственную функцию отображения ...
  • 2
    Если вы приведете пример набора результатов и ожидаемых результирующих объектов, было бы проще предоставить рекомендации о том, как сопоставлять одно с другим в C #.
Показать ещё 3 комментария
Теги:

2 ответа

1
Лучший ответ

Основываясь на ваших ответах на комментарии, кажется, что между уникальным кортежем (A, B, C) и, возможно, многими потенциально не уникальными значениями (D, E, F) взаимосвязь "один ко многим". Это поддается интерфейсу IDictionary<ABC, ICollection<DEF>>.

Когда вы используете SqlDataReader, вам все равно придется заплатить цену за итерацию, так что вы можете также получить свои объекты за один раз.

IDictionary<ABC, ICollection<DEF>> data = new Dictionary<ABC, ICollection<DEF>>();
int _a = reader.GetOrdinal("a"), _b = reader.GetOrdinal("b"), _c = reader.GetOrdinal("c");
int _value = reader.GetOrdinal("value"), _comment = reader.GetOrdinal("comment");
while (reader.Read()) {
    ABC key = new ABC { A = reader.GetInt32(_a), B = reader.GetString(_b), C = reader.GetInt32(_c) };
    ICollection<DEF> values;
    if (!data.TryGetValue(key, out values)) {
        data[key] = (values = new List<DEF>());
    }
    values.Add(new DEF { value = reader.GetInt32(_value), comment = reader.GetString(_comment) });
}

Теперь вы можете сохранить свои отношения отдельно от своей модели, но если вы хотите денормализовать их в модели представления, например, вы можете использовать:

class ABCDEF {
    public int A { get; set; }
    public string B { get; set; }
    public int C { get; set; }
    public ICollection<DEF> DEF { get; set; }
}

И заселяйте, но вы предпочитаете. Пример использования LINQ:

data.Select(d => new ABCDEF {
    A = d.Key.A,
    B = d.Key.B,
    C = d.Key.C,
    DEF = d.Value.ToArray()
});

Если вам нужно использовать структуру вышеперечисленных классов, подойдите к ней.

0

Вы можете использовать linq для создания объектов довольно чистым способом.

using (SqlDataReader reader = CallStoredProcedure())
{
   return reader.Cast<System.Data.Common.DbDataRecord>().Select(rec => new ABC()
   {
      A = (int)rec[0],
      B = rec.GetString(1),
      C = (int)rec[2],
      DEFObj = // iterate over rec[3]? Don't know what your data looks like at this point...
   }).toList();
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню