Я использую EF linq для сущностей. Мне нужно получить несколько слоев элементов для заполнения дерева. Код ниже очень медленный и долго загружается. Запрос, сгенерированный EF, похож на 200 строк (проверил это с помощью SQL Profiler).
Мне было интересно, есть ли более эффективный способ сделать это, возможно, с несколькими запросами или переупорядочением кода. Спектакль на самом деле не так хорош.
DBContext db = _DbProvider.GetContext();
List<Level1TreeviewRegion> treeList = (
from level1Item in db.Level1Table
join customer in db.Clients on level1Item.Customer_ID equals customer.Customer_ID
let rentableLocations = (from level4 in db.Location where level4.Rentable_Unit == "J" && level1Item.Customer_ID == level4.Customer_ID && level1Item.Level1_Id == level4.Level1_Id select level4).FirstOrDefault()
orderby customer.Treeview_sort_level_1_by == "n" ? level1Item.Name : "", customer.Treeview_sort_level_1_by != "n" ? level1Item.Level1_Id : 0
where level1Item.Customer_ID == customerAreaId && rentableLocations != null
select new Level1TreeviewRegion
{
Record_Number = level1Item.Record_Number,
LEVEL1_ID = level1Item.Level1_Id,
LEVEL1_NAME_WithoutCodes = !string.IsNullOrEmpty(level1Item.Name) ? level1Item.Name.Trim() : "",
LEVEL1_NAME_WithCodes = !string.IsNullOrEmpty(level1Item.Name) ? level1Item.Level1_Id + "-" + level1Item.Name.Trim() : "",
SearchString = !string.IsNullOrEmpty(level1Item.Name) ? level1Item.Level1_Id + level1Item.Name.Trim() : "",
Level2List = (from level2 in db.Level2Table
let rentableLocations1 = (from level4 in db.Location where level4.Rentable_Unit == "J" && level2.KP_PERSNEEL == level4.Customer_ID && level2.Level1_Id == level4.Level1_Id && level2.Level2_Id == level4.Level2_Id select level4).FirstOrDefault()
orderby customer.Treeview_sort_level_2_by == "n" ? level2.Name : "", customer.Treeview_sort_level_2_by != "n" ? level2.Level2_Id : ""
where level2.KP_PERSNEEL == customerAreaId && level2.Level1_Id == level1Item.Level1_Id && rentableLocations1 != null
select new Level2TreeviewRegion
{
Record_Number = level2.Record_Number,
LEVEL2_CODE = level2.Level2_Id.Trim(),
LEVEL2_NAME_WithoutCodes = !string.IsNullOrEmpty(level2.Name) ? level2.Name.Trim() : "",
LEVEL2_NAME_WithCodes = !string.IsNullOrEmpty(level2.Name) ? level2.Level2_Id.Trim() + "-" + level2.Name.Trim() : "",
SearchString = !string.IsNullOrEmpty(level2.Name) ? level2.Level2_Id.Trim() + level2.Name.Trim() : "",
LEVEL1_ID = level2.Level1_Id,
Level3List = (from level3 in db.Level3Table
let rentableLocations2 = (from level4 in db.Location where level4.Rentable_Unit == "J" && level3.Customer_ID == level4.Customer_ID && level3.Level1_Id == level4.Level1_Id && level3.Level2_Id == level4.Level2_Id && level3.Level3_Id == level4.Level3_Id select level4).FirstOrDefault()
let objectsInObjectModule = (from om in db.Object_Module where om.Customer_ID == level2.KP_PERSNEEL && om.Level2_Id == level2.Level2_Id && om.Level1_Id == level2.Level1_Id && om.ModuleId == WishModules.VB2.ToString() select om.Level3_Id)
orderby customer.Treeview_sort_level_3_by == "n" ? level3.Name : "", customer.Treeview_sort_level_3_by != "n" ? level3.Level3_Id : ""
where (level3.Level2_Id.Trim() == level2.Level2_Id.Trim() && level3.Customer_ID == customerAreaId
// extra check with the LEVEL3_MODULE table, it was Object.MJP = J, now it needs a record in the LEVEL3_MODULE table
//so if no objects are found, it is good (all are visible) OR objects are found, only they are visible
&& (!objectsInObjectModule.Any() || objectsInObjectModule.Contains(level3.Level3_Id)) && rentableLocations2 != null)
select new Level3TreeviewRegion
{
Record_Number = level3.Record_Number,
LEVEL1_ID = level3.Level1_Id,
LEVEL2_CODE = level3.Level2_Id.Trim(),
LEVEL3_CODE = level3.Level3_Id.Trim(),
LEVEL3_NAME_WithoutCodes = !string.IsNullOrEmpty(level3.Name) ? level3.Name.Trim() : "",
LEVEL3_NAME_WithCodes = !string.IsNullOrEmpty(level3.Name) ? level3.Level3_Id.Trim() + "-" + level3.Name.Trim() : "",
SearchString = !string.IsNullOrEmpty(level3.Name) ? level3.Level3_Id.Trim() + level3.Name.Trim() : "",
LEVEL3_PLAATS = level3.City.Trim(),
Ownership = string.IsNullOrEmpty(level3.Ownership) == false && (new[] { "j", "ja", "y", "yes" }).Contains(level3.Ownership.ToLower().Trim()),
Level4List = (from level4 in db.Level4Table
orderby customer.Treeview_sort_level_4_by == "n" ? level4.Description : "", customer.Treeview_sort_level_4_by != "n" ? level4.Code : ""
where level4.Rentable_Unit == "J" && level3.Level2_Id.Trim() == level4.Level2_Id.Trim() && level3.Customer_ID == level4.Customer_ID && level3.Level1_Id == level4.Level1_Id && level3.Level3_Id == level4.Level3_Id
select new Level4TreeviewRegion
{
Record_Number = level4.Record_Number,
LEVEL1_ID = level3.Level1_Id,
LEVEL2_CODE = level3.Level2_Id.Trim(),
LEVEL3_CODE = level3.Level3_Id.Trim(),
LEVEL4_CODE = level4.Code.Trim(),
LEVEL4_NAME_WithoutCodes = !string.IsNullOrEmpty(level4.Description) ? level4.Description.Trim() : "",
LEVEL4_NAME_WithCodes = !string.IsNullOrEmpty(level4.Description) ? level4.Code.Trim() + "-" + level4.Description.Trim() : "",
SearchString = !string.IsNullOrEmpty(level4.Description) ? level4.Code.Trim() + level4.Description.Trim() : "",
}).ToList()
}).ToList()
}).ToList()
}).ToList();
Соответствующая часть базы данных:
Level1Table
[RECNUM] [int] NOT NULL IDENTITY(1, 1),
[Level1_Id] [smallint] NOT NULL,
Level2Table
[RECNUM] [int] NOT NULL IDENTITY(1, 1),
[Level1_Id] [smallint] NOT NULL,
[Level2_Id] [char] (10),
[NAAM1] [char] (60),
Level3Table
[RECNUM] [int] NOT NULL IDENTITY(1, 1),
[Level1_Id] [smallint] NOT NULL,
[Level2_Id] [char] (10),
[Level3_Id] [char] (10),
[NAAM] [char] (60),
Level4Table
[RECNUM] [int] NOT NULL IDENTITY(1, 1),
[Level1_Id] [smallint] NOT NULL,
[Level2_Id] [char] (10) COLLATE,
[Level3_Id] [char] (10) COLLATE,
[Level4_Id] [char] (10) COLLATE,