我有" entities"one_answers"dtos".
Department有N Employees员工有1个(父)部门
现在我对属性名没有任何偏差。
My 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; }
}
dto:
// 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"...."的雇员属性又名"互惠";属性。
使用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;
}
}
我就差那么一点。
我使用了错误的配置方法。
我(在我的原始帖子中)正在追踪"shallowcopyforsametype"。
下面显示了"preserverreference",它阻止了stackover异常。
config.NewConfig<OrganizationEntity, Organization>()
.PreserveReference(true);
config.NewConfig<ApplicationDetailEntity, ApplicationDetail>()
.PreserveReference(true);
大声喊出答案:
使用Mapster调整导航属性
注意,这使我的Dto的水分。
我必须添加这个(下面)来让asp.net core通过网络推送object-json。
。Net Core 3.0可能的对象周期被检测到,不支持
旁注,我用我在研究时发现的另一个想法清理了一下IoC。
/* the below keeps the Mapster registrations out of the top layer, but without having to keep up with any new IRegister classes */
Type mapsterRegisterType = typeof(IRegister);
IEnumerable<Assembly> iregisterTypeAssemblies = from assembly in AppDomain.CurrentDomain.GetAssemblies()
from assemblyType in assembly.GetTypes()
where assemblyType.GetInterfaces().Contains(mapsterRegisterType)
select assembly;
TypeAdapterConfig.GlobalSettings.Scan(iregisterTypeAssemblies.Distinct().ToArray());
// TypeAdapterConfig config = new TypeAdapterConfig();
// Or
TypeAdapterConfig config = TypeAdapterConfig.GlobalSettings;
services.AddSingleton(config);
services.AddScoped<IMapper, ServiceMapper>();
和
public class MapsterConfiguration : IRegister
{
public MapsterConfiguration()
{
/* MUST have empty constructor */
}
public void Register(TypeAdapterConfig config)
{
config.NewConfig<DepartmentEntity, DepartmentDto>()
.PreserveReference(true);
config.NewConfig<EmployeeEntity, EmployeeDto>()
.PreserveReference(true);
}
}