diff --git a/api/src/Erp.Platform.Application/ListForms/Administration/ListFormQueryPreviewAppService.cs b/api/src/Erp.Platform.Application/ListForms/Administration/ListFormQueryPreviewAppService.cs index 7aa000d5..eb1f5fb1 100644 --- a/api/src/Erp.Platform.Application/ListForms/Administration/ListFormQueryPreviewAppService.cs +++ b/api/src/Erp.Platform.Application/ListForms/Administration/ListFormQueryPreviewAppService.cs @@ -7,6 +7,7 @@ using Erp.Platform.OrganizationUnits; using Erp.Platform.Queries; using Microsoft.AspNetCore.Authorization; using Volo.Abp; +using Volo.Abp.Uow; using static Erp.Platform.PlatformConsts; namespace Erp.Platform.ListForms.Administration; @@ -50,6 +51,7 @@ public class ListFormQueryPreviewAppService : PlatformAppService this.dynamicDataManager = dynamicDataManager; } + [UnitOfWork] public async Task GetListFormSelectQueryAsync(string listFormCode) { //Izin logic process @@ -62,18 +64,21 @@ public class ListFormQueryPreviewAppService : PlatformAppService //kullaniciya ait ListFormField verilerini al var fields = await listFormFieldManager.GetUserListFormFields(listFormCode); - fields = fields.Where(a => a.CanRead).ToList(); + + // Performans: Filtrelemeyi Where ile yap, tek seferde ToList() çağır + var readableFields = fields.Where(a => a.CanRead).ToList(); //kullaniciya ait Server Customization verilerini al var customizations = await listFormCustomizationManager.GetUsersServerCustomizations(listFormCode); var (_, _, dataSourceType) = await dynamicDataManager.GetAsync(listForm.IsTenant, listForm.DataSourceCode); - selectQueryManager.PrepareQueries(listForm, fields, dataSourceType, customizations); + selectQueryManager.PrepareQueries(listForm, readableFields, dataSourceType, customizations); return selectQueryManager.SelectQuery; } + [UnitOfWork] public async Task GetListFormDataQueryAsync(string listFormCode, OperationEnum op) { var authType = op switch diff --git a/api/src/Erp.Platform.Application/ListForms/ListFormSelectAppService.cs b/api/src/Erp.Platform.Application/ListForms/ListFormSelectAppService.cs index 14abf1ed..9de22582 100644 --- a/api/src/Erp.Platform.Application/ListForms/ListFormSelectAppService.cs +++ b/api/src/Erp.Platform.Application/ListForms/ListFormSelectAppService.cs @@ -162,18 +162,17 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe if (!string.IsNullOrEmpty(queryParams.Group) && !string.IsNullOrEmpty(selectQueryManager.GroupQuery)) { - //Console.WriteLine("==="); - //Console.WriteLine(selectQueryManager.GroupQuery); var data = await dynamicDataRepository.QueryAsync(selectQueryManager.GroupQuery, connectionString, param); - List<(string, int, List)> groups = []; + var dataQueryable = data.AsQueryable(); + + var groups = new List<(string, int, List)>(selectQueryManager.GroupTuples.Count); for (int i = 0; i < selectQueryManager.GroupTuples.Count; i++) { var groupTuple = selectQueryManager.GroupTuples[i]; - // var selectExpr = string.Join(",", selectQueryManager.GroupTuples.Take(i + 1).Select(a => $"{a.SelectExpr} as {a.SelectExpr}")); - var group = data.AsQueryable().GroupBy($"{groupTuple.SelectExpr}_Key").ToDynamicList(); + var group = dataQueryable.GroupBy($"{groupTuple.SelectExpr}_Key").ToDynamicList(); groups.Add((groupTuple.SelectExpr, groupTuple.Index, group)); } - var items = SetGroupItems(groups, groups.First().Item3, 0); + var items = SetGroupItems(groups, groups[0].Item3, 0); result.GroupCount = input.RequireGroupCount ? items.Count : -1; result.Data = items; @@ -231,44 +230,45 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe if (!listForm.WidgetsJson.IsNullOrWhiteSpace()) { var widgetList = JsonSerializer.Deserialize(listForm.WidgetsJson) ?? []; - foreach (var widget in widgetList.Where(w => w.IsActive)) + var activeWidgets = widgetList.Where(w => w.IsActive && !string.IsNullOrWhiteSpace(w.SqlQuery)).ToList(); + + if (activeWidgets.Count == 0) + return Widgets; + + // DataSource connection'ı bir kez al (performans) + var (dynamicDataRepository, connectionString, dataSourceType) = await dynamicDataManager.GetAsync(listForm.IsTenant, listForm.DataSourceCode); + + foreach (var widget in activeWidgets) { - if (!string.IsNullOrWhiteSpace(widget.SqlQuery)) + var w = new WidgetDto { + ColGap = widget.ColGap, + ColSpan = widget.ColSpan, + ClassName = widget.ClassName, + Items = [] + }; - var (dynamicDataRepository, connectionString, dataSourceType) = await dynamicDataManager.GetAsync(listForm.IsTenant, listForm.DataSourceCode); - - var w = new WidgetDto + var items = await dynamicDataRepository.QueryAsync(widget.SqlQuery, connectionString); + if (items != null) + { + foreach (var item in items) { - ColGap = widget.ColGap, - ColSpan = widget.ColSpan, - ClassName = widget.ClassName, - Items = [] - }; - - var items = await dynamicDataRepository.QueryAsync(widget.SqlQuery, connectionString); - if (items != null) - { - foreach (var item in items) + if (item is IDictionary dynamicItem) { - if (item is IDictionary dynamicItem) + w.Items.Add(new WidgetItemDto { - w.Items.Add(new WidgetItemDto - { - Title = dynamicItem.ContainsKey(widget.Title) ? dynamicItem[widget.Title]?.ToString() : string.Empty, - Value = dynamicItem.ContainsKey(widget.Value) ? dynamicItem[widget.Value]?.ToString() : string.Empty, - Color = dynamicItem.ContainsKey(widget.Color) ? dynamicItem[widget.Color]?.ToString() : string.Empty, - Icon = dynamicItem.ContainsKey(widget.Icon) ? dynamicItem[widget.Icon]?.ToString() : string.Empty, - SubTitle = dynamicItem.ContainsKey(widget.SubTitle) ? dynamicItem[widget.SubTitle]?.ToString() : string.Empty, - OnClick = dynamicItem.ContainsKey(widget.OnClick) ? dynamicItem[widget.OnClick]?.ToString() : string.Empty, - }); - } + Title = dynamicItem.ContainsKey(widget.Title) ? dynamicItem[widget.Title]?.ToString() : string.Empty, + Value = dynamicItem.ContainsKey(widget.Value) ? dynamicItem[widget.Value]?.ToString() : string.Empty, + Color = dynamicItem.ContainsKey(widget.Color) ? dynamicItem[widget.Color]?.ToString() : string.Empty, + Icon = dynamicItem.ContainsKey(widget.Icon) ? dynamicItem[widget.Icon]?.ToString() : string.Empty, + SubTitle = dynamicItem.ContainsKey(widget.SubTitle) ? dynamicItem[widget.SubTitle]?.ToString() : string.Empty, + OnClick = dynamicItem.ContainsKey(widget.OnClick) ? dynamicItem[widget.OnClick]?.ToString() : string.Empty, + }); } - } - - Widgets.Add(w); } + + Widgets.Add(w); } } @@ -308,53 +308,55 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe var queryParameters = httpContextAccessor.HttpContext.Request.Query.ToDictionary(x => x.Key, x => x.Value); var defaultFields = await defaultValueManager.GenerateDefaultValuesAsync(listForm, Enums.OperationEnum.Select, queryParameters: queryParameters); + // Performans: Dictionary ile hızlı lookup + var columnFormatsDict = result.ColumnFormats.ToDictionary(c => c.FieldName, c => c); foreach (var field in defaultFields) { - if (result.ColumnFormats.Any(a => a.FieldName == field.Key)) + if (columnFormatsDict.TryGetValue(field.Key, out var columnFormat)) { - result.ColumnFormats.FirstOrDefault(a => a.FieldName == field.Key).DefaultValue = field.Value; + columnFormat.DefaultValue = field.Value; } } if (!listForm.ExtraFilterJson.IsNullOrWhiteSpace()) { var extraFilterList = JsonSerializer.Deserialize(listForm.ExtraFilterJson) ?? []; - foreach (var extraFilter in extraFilterList) + var activeFilters = extraFilterList.Where(f => !string.IsNullOrWhiteSpace(f.SqlQuery)).ToList(); + + if (activeFilters.Count > 0) { - if (!string.IsNullOrWhiteSpace(extraFilter.SqlQuery)) + // DataSource connection'ı bir kez al (performans) + var (dynamicDataRepository, connectionString, dataSourceType) = + await dynamicDataManager.GetAsync(listForm.IsTenant, listForm.DataSourceCode); + + // Dictionary ile hızlı lookup + var filtersDict = result.GridOptions.ExtraFilterDto.ToDictionary(f => f.FieldName, f => f); + + foreach (var extraFilter in activeFilters) { - var (dynamicDataRepository, connectionString, dataSourceType) = - await dynamicDataManager.GetAsync(listForm.IsTenant, listForm.DataSourceCode); - var items = await dynamicDataRepository.QueryAsync(extraFilter.SqlQuery, connectionString); - if (items != null) + if (items != null && filtersDict.TryGetValue(extraFilter.FieldName, out var filter)) { - var filters = result.GridOptions.ExtraFilterDto.ToList(); - var filter = filters.FirstOrDefault(a => a.FieldName == extraFilter.FieldName); + var newItems = new List(); - if (filter != null) + foreach (var item in items) { - var newItems = new List(); - - foreach (var item in items) + if (item is IDictionary dynamicItem) { - if (item is IDictionary dynamicItem) + newItems.Add(new ExtraFilterItemsDto { - newItems.Add(new ExtraFilterItemsDto - { - Key = dynamicItem.ContainsKey("Key") ? dynamicItem["Key"]?.ToString() : null, - Value = dynamicItem.ContainsKey("Value") ? dynamicItem["Value"]?.ToString() : null - }); - } + Key = dynamicItem.ContainsKey("Key") ? dynamicItem["Key"]?.ToString() : null, + Value = dynamicItem.ContainsKey("Value") ? dynamicItem["Value"]?.ToString() : null + }); } - - filter.Items = newItems; } - // 🔑 yeniden atıyoruz ki setter çalışsın - result.GridOptions.ExtraFilterDto = filters.ToArray(); + filter.Items = newItems; } } + + // 🔑 yeniden atıyoruz ki setter çalışsın + result.GridOptions.ExtraFilterDto = filtersDict.Values.ToArray(); } }