所以我有“实体”和“dtos”。
部门有 N 个雇员 雇员有 1 个(父)部门。
现在我对属性名称没有偏差。
我的 EFCore“查询”正在获取包含(子)员工的所有部门。
我更喜欢将我的“映射”代码隔离到接口和具体。我的具体将注入 Mapster 依赖项。
// 实体
using System;
[Serializable]
public partial class DepartmentEntity
{
public int DepartmentKey { get; set; } /* PK */
public string DepartmentName { get; set; }
}
public partial class DepartmentEntity
{
public DepartmentEntity()
{
this.Employees = new List<EmployeeEntity>();
}
public ICollection<EmployeeEntity> Employees { get; set; }
}
using System;
[Serializable]
public partial class EmployeeEntity
{
public int EmployeeKey { get; set; } /* PK */
public string LastName { get; set; }
public string FirstName { get; set; }
}
public partial class EmployeeEntity
{
public DepartmentEntity ParentDepartment { get; set; }
}
Dtos:
// Different CsProject
// Dtos
using System;
[Serializable]
public partial class DepartmentDto
{
public int DepartmentKey { get; set; } /* PK */
public string DepartmentName { get; set; }
}
public partial class DepartmentDto
{
public DepartmentDto()
{
this.Employees = new List<EmployeeDto>();
}
public ICollection<EmployeeDto> Employees { get; set; }
}
using System;
[Serializable]
public partial class EmployeeDto
{
public int EmployeeKey { get; set; } /* PK */
public string LastName { get; set; }
public string FirstName { get; set; }
}
public partial class EmployeeDto
{
public DepartmentDto ParentDepartment { get; set; }
}
和 CustomerMapper 接口和具体
using System.Collections.Generic;
public interface IDepartmentConverter
{
DepartmentDto ConvertToDto(DepartmentEntity entity);
ICollection<DepartmentDto> ConvertToDtos(ICollection<DepartmentEntity> entities);
DepartmentEntity ConvertToEntity(DepartmentDto dto);
ICollection<DepartmentEntity> ConvertToEntities(ICollection<DepartmentDto> dtos);
}
using System;
using System.Collections.Generic;
using Mapster;
using MapsterMapper;
public class DepartmentConverter : IDepartmentConverter
{
public const string ErrorMessageIMapperNull = "IMapper is null";
private readonly IMapper mapper;
public DepartmentConverter(IMapper mapper)
{
this.mapper = mapper ?? throw new ArgumentNullException(ErrorMessageIMapperNull, (Exception)null);
}
public DepartmentDto ConvertToDto(DepartmentEntity entity)
{
return this.mapper.Map<Department>(entity);
}
public ICollection<DepartmentDto> ConvertToDtos(ICollection<DepartmentEntity> entities)
{
return this.mapper.Map<ICollection<Department>>(entities);
}
public ICollection<DepartmentEntity> ConvertToEntities(ICollection<DepartmentDto> dtos)
{
return this.mapper.Map<ICollection<DepartmentEntity>>(dtos);
}
public DepartmentEntity ConvertToEntity(DepartmentDto dto)
{
return this.mapper.Map<DepartmentEntity>(dto);
}
}
所以在我的 EF 获取所有部门,包括员工电话后,我有一个充分的水分
ICollection<DepartmentEntity> departmentsWithEmps
在我的处置。
但是当它通过转换/映射代码时......我得到一个“堆栈溢出”异常。
我很确定我知道为什么。它是“ParentDepartment”的 Employee 属性......也就是孩子的“互惠”属性。
对于 Newtonsoft,“修复”之一通常是这个
var json = JsonConvert.SerializeObject(harry,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
Mapster 是否有处理这种情况的配置?
以下是我的 IoC 注册尝试.......我已经尝试过,但速度很快。
namespace MyStuff
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Mapster;
using MapsterMapper;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
public class Startup
{
private string tempDebuggingConnectionString = string.Empty;
public Startup(IConfiguration configuration, IWebHostEnvironment iwhe)
{
this.Configuration = configuration;
this.WebHostEnvironment = iwhe;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment WebHostEnvironment { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
Type iregisterType = typeof(IRegister);
IEnumerable<Assembly> iregisterTypeAssemblies = from assembly in AppDomain.CurrentDomain.GetAssemblies()
from assemblyType in assembly.GetTypes()
where assemblyType.GetInterfaces().Contains(iregisterType)
select assembly;
//TypeAdapterConfig.GlobalSettings.Scan(iregisterTypeAssemblies.Distinct().ToArray());
// TypeAdapterConfig config = new TypeAdapterConfig();
// Or
//TypeAdapterConfig.GlobalSettings.Default.ShallowCopyForSameType(true);
TypeAdapterConfig config = TypeAdapterConfig.GlobalSettings;
// config.NewConfig<DepartmentDto, DepartmentEntity>()
//.ShallowCopyForSameType(true);
// config.NewConfig<DepartmentEntity, DepartmentDto>()
// .ShallowCopyForSameType(true);
// config.NewConfig<DepartmentEntity, DepartmentDto>()
// .Map(dest => dest.Employees, src => src.Employees);
// TypeAdapterSetter<DepartmentEntity, Department> orgSetter = TypeAdapterConfig<DepartmentEntity, Department>
//.NewConfig()
//.ShallowCopyForSameType(true);
// orgSetter.Config = config;
services.AddSingleton(config);
//services.AddSingleton(orgSetter);
services.AddScoped<IMapper, ServiceMapper>();
}
public void Configure(ILogger<Startup> logger, IApplicationBuilder app, IWebHostEnvironment env)
{
/* not shown */
}
}
}
虽然您可以猜到,但我的 EFCore 代码如下所示:
public async Task<IEnumerable<DepartmentDto>> GetAllAsync(CancellationToken token)
{
List<DepartmentEntity> entities = await this.entityDbContext.Departments.Include(ent => ent.ApplicationDetails).AsNoTracking().ToListAsync(token);
try
{
/* below is injected, but new'ing it up here for SOF question */
IDepartmentConverter localNonInjectedConverter = new DepartmentConverter(/* again, not my real code....my IoC has the Mapster object */);
ICollection<DepartmentDto> returnItems = localNonInjectedConverter.ConvertToDtos(entities);
return returnItems;
}
catch (Exception ex)
{
throw ex;
}
}