Support AutoMapper's ProjectTo in DataSourceLoader
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- csharp
- Lĩnh vực
- backend, backend-api-design
Hướng nghiên cứu
Bắt đầu tại điểm vào DataSourceLoader.Load và theo dõi cách áp dụng việc lọc, sắp xếp, nhóm và projection. So sánh luồng này với workaround AutoMapper ProjectTo trong issue; công việc được hoàn tất khi các thao tác DataSourceLoader có thể chạy trước projection DTO mà vẫn giữ nguyên metadata của kết quả được trả về.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
As described in https://www.devexpress.com/Support/Center/Question/Details/T758528/modify-the-datasourceloader-to-support-projection-as-part-of-the-original-query-operation and referenced threads - repeated below for simplicity
In a nutshell, the issue is this;
It is best practice in EF to return a DTO rather than the original object. Regardless of best practice, efficiency demands in so in my application as I have tables with large text fields that are not necessary for populating lists and would increase the size of the payload over 100x. I get the data for my lists using DataSourceLoader GET controllers, and I use filtering, sorting and grouping in the DataSourceLoader extensively. I ProjectTo to ensure that my payload from SQL to API, and my payload from API to client are efficient and contain no more data that is necessary.
At the moment, it is impossible to perform operations on the full set of object properties, but return only a subset using ProjectTo. Any property specified in the options e.g. a filter occurs after the ProjectTo, so the property is not available for filtering at that point in the SQL. As per the ticket, you cannot simply operate on the data after it is returned, as it breaks other elements of the returned set for more complex operations like grouping.
Also, a Select is not the answer as this requires far too much hard coding to move between types - this is what automapper and ProjectTo are for.
At the moment I have created a workaround that;
- Returns the DataSourceLoader result if a Select is specified (obviously no projection is required in this case)
- Programatically identifies the key of the original entity (e.g. User => UserId)
- Runs the DataSourceLoader without Projecting, but returning only the Id of the entity - at this point I have all of the IDs matching the original query - IDset
- Performs a simple where(x=>IDset.Contains(x=>[IDProperty])).ProjectTo()
This works, but it would be far better if the datasourceloader could be modified to append my projection so it occurs after the datasourceloader filtering / sorting / grouping. I can't see that this would require much modification.
My code below for anyone else with this issue.
var src = _context.Approval.Where(x =>
x.ProjectId == _userService.Project_ID &&
x.PublishDate != null &&
x.NewApprovalId == null).Include(x => x.ApprovalTo);
var result = _context.FilterAsDto<Approval, ApprovalListDto>(src, loadOptions);
public LoadResult FilterAsDto<T, TDto>(Func<T, bool> preFilter, DataSourceLoadOptions loadOptions) where T : class
{
var qryResult = DataSourceLoader.Load(Set<T>().Where(preFilter), loadOptions);
if (loadOptions.Select == null || loadOptions.Select.Count()==0) return FilterAsDto<T, TDto>(qryResult, loadOptions);
else return qryResult;
}
public LoadResult FilterAsDto<T, TDto>(IQueryable<T> sourceQuery, DataSourceLoadOptions loadOptions) where T : class
{
var qryResult = DataSourceLoader.Load(sourceQuery, loadOptions);
if (loadOptions.Select == null || loadOptions.Select.Count() == 0) return FilterAsDto<T, TDto>(qryResult, loadOptions);
else return qryResult;
}
private LoadResult FilterAsDto<T, TDto>(LoadResult loadedData, DataSourceLoadOptions loadOptions) where T : class
{
var pkey = Model.FindEntityType(typeof(T)).FindPrimaryKey().Properties.Select(n => n.Name).Single();
var pKeyExp = Expression.Parameter(typeof(T));
var pKeyProperty = Expression.PropertyOrField(pKeyExp, pkey);
var keySelector = Expression.Lambda<Func<T, int>>(pKeyProperty, pKeyExp).Compile();
if (loadedData.data is IEnumerable<Group>) return loadedData;
else
{
var OriginalSummary = loadedData.summary;
List<int> idList = loadedData.data.Cast<T>().Select(keySelector).ToList();
var pKeyExpDto = Expression.Parameter(typeof(TDto));
var pKeyPropertyDto = Expression.PropertyOrField(pKeyExpDto, pkey);
var method = idList.GetType().GetMethod("Contains");
var call = Expression.Call(Expression.Constant(idList), method, pKeyPropertyDto);
var lambda = Expression.Lambda<Func<TDto, bool>>(call, pKeyExpDto);
var defOptions = new DataSourceLoadOptionsBase();
defOptions.Sort = loadOptions.Sort;
defOptions.RequireTotalCount = loadOptions.RequireTotalCount;
var returnData= DataSourceLoader.Load(Set<T>().ProjectTo<TDto>(_mapper.ConfigurationProvider).Where(lambda), defOptions);
returnData.summary = OriginalSummary;
returnData.totalCount = loadedData.totalCount;
return returnData;
}
}
- Ngôn ngữ chính
- C#
- Star
- 165
- Fork
- 140
- Merge trung bình
- 1 ngày 2 giờ
- Pull request đã merge (30 ngày)
- 4
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của DevExpress/DevExtreme.AspNet.Data
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 78/100
-
Provide additional parameters to support provision of execution context to Load and LoadAsync Đang mở
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
DevExpress/DevExtreme.AspNet.Data#588 · 3 bình luận ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
-
Dependency Dashboard Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 15/100
-
ES6 support Đang mởenhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
Tất cả issue của DevExpress/DevExtreme.AspNet.Data
Issue tương tự
-
type/automation type/tech-debt
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
-
t/bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
-
ci-failure-cause test-failure
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
-
area:auth FE mvp P3
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
klasolsson81/jobbliggaren#1788 ·