Я работаю над созданием объекта с вложенной иерархией из сплющенного списка элементов спецификации (ведомости материалов) из SQL, которые содержат уровень спецификации и родителя, которому они принадлежат. По сути, каждый родительский элемент, представляющий собой сборку из меньших частей, должен добавлять свои части в коллекцию этого объекта. Я считаю, что у нас есть некоторые части, которые могут повторяться до 10 уровней, и мне не нравится, как работает этот шаблон.
Этот набор данных взят из хранимой процедуры, которая выполняет сложный запрос CTE, и я не заинтересован в том, чтобы пытаться заставить эту работу работать с Entity Framework, так как у нас много баз данных, и нам нужен лучший контроль над SQL, который мы пишем (отсюда и хранимая процедура). В конечном итоге это будет JSON, который я буду отображать как свернутое дерево в браузере.
Вот уродливая часть, которую я надеюсь немного почистить. Суть того, что здесь происходит, прежде чем я начну повторять различные уровни:
- Установить первый элемент (не полный, но это основной элемент).
- Выполнить хранимую процедуру (с параметром) для возврата таблицы данных.
- Создать плоский список объектов, которые я хочу вложить.
- Получите общее количество вложенных уровней, существующих в спецификации.
- Перебирайте все уровни очень уродливо.
public BOMItemModel GetItemBOM(string item)
{
try
{
var bom = new BOMItemModel { PLPartNumber = item, BOMLevel = 0 };
var par = new Hashtable();
par.Add("@Item", item);
var dt = db.GetDataTable("[part].[getItemBOM]", par);
var bomList = new List<BOMItemModel>();
foreach(DataRow r in dt.Rows)
{
bomList.Add(MapBomItem(r));
}
var bomLevels = bomList.Max(x => x.BOMLevel);
for(var i = 1; i < bomLevels; i++)
{
foreach (var b in bomList.Where(x => x.BOMLevel == i).ToList())
{
if (i == 1)
{
bom.SubItems.Add(b);
}
else
{
if (i == 2)
{
var lvl2Items = bom.SubItems;
var parent1 = lvl2Items.FirstOrDefault(x => x.PLPartNumber == b.ParentPLNumber);
if (parent1 != null) parent1.SubItems.Add(b);
}
if (i == 3)
{
var lvl2Items = bom.SubItems;
foreach(var lvl2 in lvl2Items)
{
var lvl3Items = lvl2.SubItems;
var parent2 = lvl3Items.FirstOrDefault(x => x.PLPartNumber == b.ParentPLNumber);
if (parent2 != null) parent2.SubItems.Add(b);
}
}
if (i == 4)
{
var lvl2Items = bom.SubItems;
foreach (var lvl2 in lvl2Items)
{
var lvl3Items = lvl2.SubItems;
foreach (var lvl3 in lvl3Items)
{
var lvl4Items = lvl3.SubItems;
var parent3 = lvl4Items.FirstOrDefault(x => x.PLPartNumber == b.ParentPLNumber);
if (parent3 != null) parent3.SubItems.Add(b);
}
}
}
if (i == 5)
{
var lvl2Items = bom.SubItems;
foreach (var lvl2 in lvl2Items)
{
var lvl3Items = lvl2.SubItems;
foreach (var lvl3 in lvl3Items)
{
var lvl4Items = lvl3.SubItems;
foreach (var lvl4 in lvl4Items)
{
var lvl5Items = lvl4.SubItems;
var parent4 = lvl5Items.FirstOrDefault(x => x.PLPartNumber == b.ParentPLNumber);
if (parent4 != null) parent4.SubItems.Add(b);
}
}
}
}
if (i == 6)
{
var lvl2Items = bom.SubItems;
foreach (var lvl2 in lvl2Items)
{
var lvl3Items = lvl2.SubItems;
foreach (var lvl3 in lvl3Items)
{
var lvl4Items = lvl3.SubItems;
foreach (var lvl4 in lvl4Items)
{
var lvl5Items = lvl4.SubItems;
foreach (var lvl5 in lvl5Items)
{
var lvl6Items = lvl5.SubItems;
var parent5 = lvl6Items.FirstOrDefault(x => x.PLPartNumber == b.ParentPLNumber);
if (parent5 != null) parent5.SubItems.Add(b);
}
}
}
}
}
}
}
}
return bom;
}
catch (Exception ex)
{
Log.Error(ex.Message, ex);
}
return null;
}
Вот так выглядит моя модель или класс:
public class BOMItemModel
{
public BOMItemModel()
{
SubItems = new List<BOMItemModel>();
}
public string ParentPLNumber { get; set; }
public string PartNumber { get; set; }
public string PartListName { get; set; }
public string ItemNumber { get; set; }
public string PLPartNumber { get; set; }
public string PartType { get; set; }
public string PLManufacturer { get; set; }
public string PLDescription { get; set; }
public decimal Qty { get; set; }
public int BOMLevel { get; set; }
public List<BOMItemModel> SubItems { get; set; }
}
Последнее свойство этого класса - это то, где я вставляю подпункты родительского элемента, и это может вложить несколько уровней вглубь.