如何使用 ICollection 和 IList 为实体和 DTO 创建映射
How to CreateMap for Entity and DTO with ICollection and IList
我在 AutoMapper 中的映射有问题。
我尝试使用 ForMember 函数,但连接映射时仍然出现错误。
如何为此实体创建映射?
我创建了一个 AutoMapping class:
public class AutoMapping : Profile
{
public AutoMapping()
{
CreateMap<Member, MemberDto>()
.ForMember(dest => dest.Groups, opt => { opt.MapFrom(src => src.GroupMember.Select(x => x.Group)); });
CreateMap<Group, GroupDto>()
.ForMember(dest => dest.Members, opt => { opt.MapFrom(src => src.GroupMember.Select(x => x.Member)); });
}
}
我试过这样使用它:
public async Task<Page<MemberDto>> GetPaginatedAsync(IDataTablesRequest request)
{
Filters<MemberDto> filters = GetFiltersFromRequest(request);
Sorts<MemberDto> sorts = GetSortsFromRequest(request);
var currentPage = request.Start / request.Length + 1;
var pageSize = request.Length;
try
{
return await _context.Member
.Include(gm => gm.GroupMember)
.ThenInclude(g => g.Group)
.Select(m => _mapper.Map<MemberDto>(m))
.PaginateAsync(currentPage, pageSize, sorts, filters);
}
catch (Exception ex)
{
throw ex; //Log it
}
}
在接下来的步骤中,我将对其余实体进行相同的操作,但请给我一些提示:)
编辑:使用后
.ProjectTo<MemberDto>(_mapper.ConfigurationProvider)
.PaginateAsync(currentPage, pageSize, sorts, filters);
我收到类似
的错误
The LINQ expression 'DbSet<Member>
.Where(m => DbSet<GroupMember>
.Where(g => EF.Property<Nullable<int>>(m, "MemberId") != null && EF.Property<Nullable<int>>(m, "MemberId") == EF.Property<Nullable<int>>(g, "MemberId"))
.Join(
outer: DbSet<Group>,
inner: g => EF.Property<Nullable<int>>(g, "GroupId"),
outerKeySelector: g0 => EF.Property<Nullable<int>>(g0, "GroupId"),
innerKeySelector: (o, i) => new TransparentIdentifier<GroupMember, Group>(
Outer = o,
Inner = i
))
.Select(g => new GroupDto{
CreatedDate = g.Inner.CreatedDate,
DeletedDate = g.Inner.DeletedDate,
GroupId = g.Inner.GroupId,
IsActive = g.Inner.IsActive,
Members = DbSet<GroupMember>
.Where(g1 => EF.Property<Nullable<int>>(g.Inner, "GroupId") != null && EF.Property<Nullable<int>>(g.Inner, "GroupId") == EF.Property<Nullable<int>>(g1, "GroupId"))
.Join(
outer: DbSet<Member>,
inner: g1 => EF.Property<Nullable<int>>(g1, "MemberId"),
outerKeySelector: m0 => EF.Property<Nullable<int>>(m0, "MemberId"),
innerKeySelector: (o, i) => new TransparentIdentifier<GroupMember, Member>(
Outer = o,
Inner = i
))
.Select(g1 => new MemberDto{
CreatedDate = g1.Inner.CreatedDate,
DateOfBirth = g1.Inner.DateOfBirth,
Email = g1.Inner.Email,
FirstName = g1.Inner.FirstName,
IsActive = g1.Inner.IsActive,
LastName = g1.Inner.LastName,
MemberId = g1.Inner.MemberId,
PhoneNumber = g1.Inner.PhoneNumber,
UpdatedDate = g1.Inner.UpdatedDate
}
)
.ToList(),
Name = g.Inner.Name,
UpdatedDate = g.Inner.UpdatedDate
}
)
.ToList()
.Any(g => g.Name.Contains(__column_Search_Value_0)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
EDIT2:我用它来分页和过滤:
https://github.com/wdunn001/EntityFrameworkPaginateCore/tree/master/EntityFrameworkPaginateCore
编辑 3:
private static Sorts<MemberDto> GetSortsFromRequest(IDataTablesRequest request)
{
var sorts = new Sorts<MemberDto>();
foreach (var column in request.Columns.Where(x => x.IsSortable && x.Sort != null))
{
switch (column.Field)
{
case "firstName":
sorts.Add(true, x => x.FirstName, column.Sort.Direction != SortDirection.Ascending);
break;
case "lastName":
sorts.Add(true, x => x.LastName, column.Sort.Direction != SortDirection.Ascending);
break;
case "email":
sorts.Add(true, x => x.Email, column.Sort.Direction != SortDirection.Ascending);
break;
case "phoneNumber":
sorts.Add(true, x => x.PhoneNumber, column.Sort.Direction != SortDirection.Ascending);
break;
default:
break;
}
}
return sorts;
}
private static Filters<MemberDto> GetFiltersFromRequest(IDataTablesRequest request)
{
var filters = new Filters<MemberDto>();
foreach (var column in request.Columns
.Where(x => x.IsSearchable && x.Search != null &&
!string.IsNullOrWhiteSpace(x.Search.Value))
)
{
switch (column.Field)
{
case "firstName":
filters.Add(true, x => x.FirstName.Contains(column.Search.Value));
break;
case "lastName":
filters.Add(true, x => x.LastName.Contains(column.Search.Value));
break;
case "email":
filters.Add(true, x => x.Email.Contains(column.Search.Value));
break;
case "phoneNumber":
filters.Add(true, x => x.PhoneNumber.Contains(column.Search.Value));
break;
case "groups":
filters.Add(true, x => x.Groups.Any(g => g.Name.Contains(column.Search.Value)));
break;
default:
break;
}
}
return filters;
}
编辑 4:
CreateMap<Member, MemberDto>()
.ForMember(dest => dest.Groups,
opt => { opt.MapFrom(src => src.GroupMember); });
删除 SELECT 后出现错误:
Missing map from CMSport.Context.Models.GroupMember to CMSport.Dto.GroupDto. Create using CreateMap<GroupMember, GroupDto>.
解决方案:
1. 按 Member 过滤和排序,而不是按 MemberDto
2.将Dtos设置为[JsonObject(IsReference = true)]
3.像这样在PaginateAsync之后映射它
var page = await _context.Member
.Include(x => x.GroupMember)
.ThenInclude(x => x.Group)
.PaginateAsync(currentPage, pageSize, sorts, filters);
return new Page<MemberDto>
{
CurrentPage = page.CurrentPage,
PageCount = page.PageCount,
PageSize = page.PageSize,
RecordCount = page.RecordCount,
Results = page.Results.Select(x => _mapper.Map<MemberDto>(x))
};
我想你在
中遇到了将 LINQ
翻译成 SQL
的错误
.Select(m => _mapper.Map<MemberDto>(m))
显然,_mapper.Map<MemberDto>(m)
无法转换为 SQL
,因此您可以尝试使用 .ProjectTo<MemberDto>()
(参见 QuarableExtensions)代替该行,以便查询看起来像
return await _contesnxt.Member
.ProjectTo<MemberDto>()
.PaginateAsync(currentPage, pageSize, sorts, filters);
我在 AutoMapper 中的映射有问题。
我尝试使用 ForMember 函数,但连接映射时仍然出现错误。
如何为此实体创建映射?
我创建了一个 AutoMapping class:
public class AutoMapping : Profile
{
public AutoMapping()
{
CreateMap<Member, MemberDto>()
.ForMember(dest => dest.Groups, opt => { opt.MapFrom(src => src.GroupMember.Select(x => x.Group)); });
CreateMap<Group, GroupDto>()
.ForMember(dest => dest.Members, opt => { opt.MapFrom(src => src.GroupMember.Select(x => x.Member)); });
}
}
我试过这样使用它:
public async Task<Page<MemberDto>> GetPaginatedAsync(IDataTablesRequest request)
{
Filters<MemberDto> filters = GetFiltersFromRequest(request);
Sorts<MemberDto> sorts = GetSortsFromRequest(request);
var currentPage = request.Start / request.Length + 1;
var pageSize = request.Length;
try
{
return await _context.Member
.Include(gm => gm.GroupMember)
.ThenInclude(g => g.Group)
.Select(m => _mapper.Map<MemberDto>(m))
.PaginateAsync(currentPage, pageSize, sorts, filters);
}
catch (Exception ex)
{
throw ex; //Log it
}
}
在接下来的步骤中,我将对其余实体进行相同的操作,但请给我一些提示:)
编辑:使用后
.ProjectTo<MemberDto>(_mapper.ConfigurationProvider)
.PaginateAsync(currentPage, pageSize, sorts, filters);
我收到类似
的错误The LINQ expression 'DbSet<Member>
.Where(m => DbSet<GroupMember>
.Where(g => EF.Property<Nullable<int>>(m, "MemberId") != null && EF.Property<Nullable<int>>(m, "MemberId") == EF.Property<Nullable<int>>(g, "MemberId"))
.Join(
outer: DbSet<Group>,
inner: g => EF.Property<Nullable<int>>(g, "GroupId"),
outerKeySelector: g0 => EF.Property<Nullable<int>>(g0, "GroupId"),
innerKeySelector: (o, i) => new TransparentIdentifier<GroupMember, Group>(
Outer = o,
Inner = i
))
.Select(g => new GroupDto{
CreatedDate = g.Inner.CreatedDate,
DeletedDate = g.Inner.DeletedDate,
GroupId = g.Inner.GroupId,
IsActive = g.Inner.IsActive,
Members = DbSet<GroupMember>
.Where(g1 => EF.Property<Nullable<int>>(g.Inner, "GroupId") != null && EF.Property<Nullable<int>>(g.Inner, "GroupId") == EF.Property<Nullable<int>>(g1, "GroupId"))
.Join(
outer: DbSet<Member>,
inner: g1 => EF.Property<Nullable<int>>(g1, "MemberId"),
outerKeySelector: m0 => EF.Property<Nullable<int>>(m0, "MemberId"),
innerKeySelector: (o, i) => new TransparentIdentifier<GroupMember, Member>(
Outer = o,
Inner = i
))
.Select(g1 => new MemberDto{
CreatedDate = g1.Inner.CreatedDate,
DateOfBirth = g1.Inner.DateOfBirth,
Email = g1.Inner.Email,
FirstName = g1.Inner.FirstName,
IsActive = g1.Inner.IsActive,
LastName = g1.Inner.LastName,
MemberId = g1.Inner.MemberId,
PhoneNumber = g1.Inner.PhoneNumber,
UpdatedDate = g1.Inner.UpdatedDate
}
)
.ToList(),
Name = g.Inner.Name,
UpdatedDate = g.Inner.UpdatedDate
}
)
.ToList()
.Any(g => g.Name.Contains(__column_Search_Value_0)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
EDIT2:我用它来分页和过滤:
https://github.com/wdunn001/EntityFrameworkPaginateCore/tree/master/EntityFrameworkPaginateCore
编辑 3:
private static Sorts<MemberDto> GetSortsFromRequest(IDataTablesRequest request)
{
var sorts = new Sorts<MemberDto>();
foreach (var column in request.Columns.Where(x => x.IsSortable && x.Sort != null))
{
switch (column.Field)
{
case "firstName":
sorts.Add(true, x => x.FirstName, column.Sort.Direction != SortDirection.Ascending);
break;
case "lastName":
sorts.Add(true, x => x.LastName, column.Sort.Direction != SortDirection.Ascending);
break;
case "email":
sorts.Add(true, x => x.Email, column.Sort.Direction != SortDirection.Ascending);
break;
case "phoneNumber":
sorts.Add(true, x => x.PhoneNumber, column.Sort.Direction != SortDirection.Ascending);
break;
default:
break;
}
}
return sorts;
}
private static Filters<MemberDto> GetFiltersFromRequest(IDataTablesRequest request)
{
var filters = new Filters<MemberDto>();
foreach (var column in request.Columns
.Where(x => x.IsSearchable && x.Search != null &&
!string.IsNullOrWhiteSpace(x.Search.Value))
)
{
switch (column.Field)
{
case "firstName":
filters.Add(true, x => x.FirstName.Contains(column.Search.Value));
break;
case "lastName":
filters.Add(true, x => x.LastName.Contains(column.Search.Value));
break;
case "email":
filters.Add(true, x => x.Email.Contains(column.Search.Value));
break;
case "phoneNumber":
filters.Add(true, x => x.PhoneNumber.Contains(column.Search.Value));
break;
case "groups":
filters.Add(true, x => x.Groups.Any(g => g.Name.Contains(column.Search.Value)));
break;
default:
break;
}
}
return filters;
}
编辑 4:
CreateMap<Member, MemberDto>()
.ForMember(dest => dest.Groups,
opt => { opt.MapFrom(src => src.GroupMember); });
删除 SELECT 后出现错误:
Missing map from CMSport.Context.Models.GroupMember to CMSport.Dto.GroupDto. Create using CreateMap<GroupMember, GroupDto>.
解决方案:
1. 按 Member 过滤和排序,而不是按 MemberDto
2.将Dtos设置为[JsonObject(IsReference = true)]
3.像这样在PaginateAsync之后映射它
var page = await _context.Member
.Include(x => x.GroupMember)
.ThenInclude(x => x.Group)
.PaginateAsync(currentPage, pageSize, sorts, filters);
return new Page<MemberDto>
{
CurrentPage = page.CurrentPage,
PageCount = page.PageCount,
PageSize = page.PageSize,
RecordCount = page.RecordCount,
Results = page.Results.Select(x => _mapper.Map<MemberDto>(x))
};
我想你在
中遇到了将LINQ
翻译成 SQL
的错误
.Select(m => _mapper.Map<MemberDto>(m))
显然,_mapper.Map<MemberDto>(m)
无法转换为 SQL
,因此您可以尝试使用 .ProjectTo<MemberDto>()
(参见 QuarableExtensions)代替该行,以便查询看起来像
return await _contesnxt.Member
.ProjectTo<MemberDto>()
.PaginateAsync(currentPage, pageSize, sorts, filters);