在实体框架核心中将字典转换为ICollection
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在实体框架核心中将字典转换为ICollection相关的知识,希望对你有一定的参考价值。
在这里,我坚持在EF Core中将dictionary
转换为Icollection
。我在Dictionary
类中有FlatEmployee
,其中我在数据库中存储键,值对的列表。我这样宣布:
public class FlatEmployee
{
public int EmployeeId { get; set; }
public Dictionary<string, long> PayAndAllowances { get; set; }
}
//====================Configuration
public void Configure(EntityTypeBuilder<FlatEmployee> builder)
{
builder.HasKey(f => new { f.EmployeeId });
builder.Property(sb => sb.PayAndAllowances)
.HasConversion(
pa => JsonConvert.SerializeObject(pa),
pa => JsonConvert.DeserializeObject<Dictionary<string, long>>(pa));
}
当我播种或插入时,这非常好。但是当我试图获得FlatEmployee类时,我面临的问题。这是因为我想在Collection中获取字典。为此我已经宣布了另一个类:
public class LastPayCertificateViewModel: IHaveCustomMapping
{
public int EmployeeCode { get; set; }
public EmployeeEarningDTO PayAndAllowances { get; set; }
public void CreateMappings(Profile configuration)
{
configuration.CreateMap<FlatEmployee, LastPayCertificateViewModel>()
.ForMember(dto => dto.EmployeeCode , opt => opt.MapFrom(entity => entity.EmployeeId ));
}
}
public class EmployeeEarningDTO : IHaveCustomMapping
{
public ICollection<BaseEmployeeDictionary> PayAndAllowances { get; set; }
public void CreateMappings(Profile configuration)
{
configuration.CreateMap<FlatEmployee, EmployeeEarningDTO>()
.ForMember(dto => dto.PayAndAllowances, opt => opt.MapFrom(entity => entity.PayAndAllowances));
}
}
public class BaseEmployeeDictionary
{
public string Name { get; set; }
public long Amount { get; set; }
}
当我尝试使用上面的类来获取这样的数据时:
public class LastPayCertificateQuery : IRequest<LastPayCertificateViewModel>
{
public string EmployeeCode { get; set; }
}
public async Task<LastPayCertificateViewModel> Handle(LastPayCertificateQuery request, CancellationToken cancellationToken)
{
var predicate = PredicateBuilder.False<FlatEmployee>();
predicate = predicate.Or(emp => emp.EmployeeId == request.EmployeeCode);
var employee = await _context.FlatEmployee
.Where(predicate)
.FirstOrDefaultAsync(cancellationToken);
if (employee == null)
return null;
var empVM = _mapper.Map<LastPayCertificateViewModel>(employee);
}
然后我在PayAndAllowances in empVM
得到null。这就是我的问题所在。我的问题在哪里?我认为这是因为该词典具有键值对,并且无法转换为BaseEmployeeDictionary
。我也试过这种方式将列表项添加到PayAndAllowances in empVM
foreach (KeyValuePair<string, long> data in employee.DeductionsByAdjustment)
{
BaseEmployeeDictionary listItem = new BaseEmployeeDictionary
{
Name = data.Key,
Amount = data.Value
};
empVM.EarningDetails.PayAndAllowances.Add(listItem);
return empVM;
}
这当然不会工作,因为empVM.EarningDetails.PayAndAllowances
为null并抛出NullReferenceException。我的查询是如何在EmployeeEarningDTO
中创建地图时在Dictionary和ICollection之间进行映射。或者请您提出宝贵的建议和解决方案。
事实证明是AutoMapper映射问题。
首先,与EmployeeEarningDTO
相比,LastPayCertificateViewModel
内部的FlatEmployee
创造了额外的水平:
LastPayCertificateViewModel.PayPayAndAllowances.PayAndAllowances
VS
FlatEmployee.PayAndAllowances
AutoMapper默认使用相同名称映射属性。因此,在FlatEmployee
到LastPayCertificateViewModel
地图内,它会尝试将Dictionary<string, long> PayAndAllowances
映射到EmployeeEarningDTO PayAndAllowances
。但是没有从Dictionary<string, long>
到EmployeeEarningDTO
的映射。相反,有一个从FlatEmployee
到EmployeeEarningDTO
的映射,所以你必须告诉AM使用它:
configuration.CreateMap<FlatEmployee, LastPayCertificateViewModel>()
.ForMember(dto => dto.EmployeeCode, opt => opt.MapFrom(entity => entity.EmployeeId))
.ForMember(dto => dto.PayAndAllowances, opt => opt.MapFrom(entity => entity)); // <--
其次,从FlatEmployee
映射到EmployeeEarningDTO
- AM将自动尝试映射PayAndAllowances
属性,但没有从KeyValuePair<string, long>
到BaseEmployeeDictionary
的映射。您可以定义此类映射
configuration.CreateMap<KeyValuePair<string, long>, BaseEmployeeDictionary>()
.ForMember(dst => dst.Name, opt => opt.MapFrom(src => src.Key))
.ForMember(dst => dst.Amount, opt => opt.MapFrom(src => src.Value));
这将允许您简单地使用
configuration.CreateMap<FlatEmployee, EmployeeEarningDTO>();
但是你可能不会这样做,因为你不希望每个KeyValuePair<string, long>
被映射到BaseEmployeeDictionary
,所以你可以在那里进行映射:
configuration.CreateMap<FlatEmployee, EmployeeEarningDTO>()
.ForMember(dto => dto.PayAndAllowances, opt => opt.MapFrom(entity => entity.PayAndAllowances
.Select(src => new BaseEmployeeDictionary { Name = src.Key, Amount = src.Value })));
以上是关于在实体框架核心中将字典转换为ICollection的主要内容,如果未能解决你的问题,请参考以下文章
如何将afnetworking json字典转换为字符串,然后在IOS中将字符串转换为字典?