我有一个包含4个类的项目:Direction,Area,Section和Local。方向有很多区域,区域有很多区域,区域有很多当地人。本地有正面的本地人和负面的本地人,因此本地实体将有自己的多对多关系。我使用Automapper将LocalDto转换为Local,但是当我尝试使用positives locals和/或negatives locals更新此实体时,系统会生成此异常:
操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
所以,它们是我的实体的mapper类:
******* ******* DirectionMapper
public static class DirectionMappers
{
public static void SettingMappingDirectionToDirectionDto()
{
Mapper.CreateMap<Direction, DirectionDto>()
.ForMember(directionDto => directionDto.AreasDtosList,
mc => mc.MapFrom(direction => direction.AreasCollection));
}
public static void SettingMappingDirectionDtoToDirection()
{
Mapper.CreateMap<DirectionDto, Direction>()
.ForMember(direction => direction.AreasCollection,
mc => mc.MapFrom(directionDto => directionDto.AreasDtosList));
}
public static void SettingMappingDirectionToString()
{
Mapper.CreateMap<Direction, string>().ConvertUsing(direction => direction.Name ?? string.Empty);
}
}
******** AreaMapper **********
public class AreaMappers
{
public static void SettingMappingAreaToAreaDto()
{
Mapper.CreateMap<Area, AreaDto>()
.ForMember(areaDto => areaDto.SectionsDtosList, mc => mc.MapFrom(area => area.SectionsCollection))
.ForMember(areaDto => areaDto.DirectionDto, mc => mc.MapFrom(area => area.Direction));
}
public static void SettingMappingAreaDtoToArea()
{
Mapper.CreateMap<AreaDto, Area>()
.ForMember(area => area.SectionsCollection, mc => mc.MapFrom(areaDto => areaDto.SectionsDtosList))
.ForMember(area => area.Direction,mc=> mc.MapFrom(areaDto=> areaDto.DirectionDto));
}
public static void SettingMappingAreaToString()
{
Mapper.CreateMap<Area, string>().ConvertUsing(area => area.Name ?? string.Empty);
}
}
****** SectionMapper *******************
public class SectionMappers
{
public static void SettingMappingSectionToSectionDto()
{
Mapper.CreateMap<Section, SectionDto>()
.ForMember(sectionDto => sectionDto.LocalsDtosList, mc => mc.MapFrom(section => section.LocalsCollection))
.ForMember(sectionDto => sectionDto.AreaDto, mc => mc.MapFrom(section => section.Area));
}
public static void SettingMappingSectionDtoToSection()
{
Mapper.CreateMap<SectionDto, Section>()
.ForMember(section => section.LocalsCollection,
mc => mc.MapFrom(sectionDto => sectionDto.LocalsDtosList))
.ForMember(section => section.Area, mc => mc.MapFrom(sectionDto => sectionDto.AreaDto));
}
public static void SettingMappingSectionToString()
{
Mapper.CreateMap<Section, string>().ConvertUsing(section => section.Name ?? string.Empty);
}
}
****** LocalMapper(主菜)******
public static class LocalMappers
{
public static void SettingMappingLocalToLocalDto()
{
Mapper.CreateMap<Local, LocalDto>()
.ForMember(localDto => localDto.PositivesLocalsDtos,
mc => mc.MapFrom(local => local.PositivesLocals)
)
.ForMember(localDto => localDto.NegativesLocalsDtos,
mc => mc.MapFrom(local => local.NegativesLocals)
)
.ForMember(localDto => localDto.SectionDto, mc => mc.MapFrom(local => local.Section));
}
public static void SettingMappingLocalDtoToLocal()
{
Mapper.CreateMap<LocalDto, Local>()
.ForMember(local => local.PositivesLocals,
mc => mc.MapFrom(localDto => localDto.PositivesLocalsDtos)
)
.ForMember(local => local.NegativesLocals,
mc => mc.MapFrom(localDto => localDto.NegativesLocalsDtos)
)
.ForMember(local => local.Section, mc => mc.MapFrom(localDto => localDto.SectionDto));
}
public static void SettingMappingLocalToString()
{
Mapper.CreateMap<Local, string>().ConvertUsing(local => local.Number ?? string.Empty);
}
}
嗯,这是本地更新的服务方法:
public AppOperationResult Update(int id, LocalDto localDto)
{
var appOperationResult = CommunValidations.IsDtoNull(localDto);
if (appOperationResult != null) return appOperationResult;
var tupleValidation = localDto.IsModelDtoValidateForUpdate(id);
var isValidate = tupleValidation.Item1;
if (isValidate)
{
if (TryUpdateLocalFromLocalDto(id, localDto)) return AppOperationResult.Successful();
}
string messageError = tupleValidation.Item2;
return AppOperationResult.WithError(messageError);
}
这些是我添加正面和负面局部的方法(我称之为AdjacentLocals):
public AppOperationResult AddAdjacentLocalsToLocal(AdjacentLocalsToLocalDto adjacentLocalsToLocal)
{
var localDto = adjacentLocalsToLocal.LocalToModify;
var appOperationResult = CommunValidations.IsDtoNull(localDto);
if (appOperationResult != null) return appOperationResult;
var tupleValidation = localDto.IsModelDtoValidate();
var isValidate = tupleValidation.Item1;
if (isValidate)
{
if (TryToAddAdjacentLocalsToLocal(adjacentLocalsToLocal, localDto))
return AppOperationResult.Successful();
}
string messageError = tupleValidation.Item2;
return AppOperationResult.WithError(messageError);
}
private bool TryToAddAdjacentLocalsToLocal(AdjacentLocalsToLocalDto adjacentLocalsToLocal, LocalDto localDto)
{
var positiveLocals = adjacentLocalsToLocal.PositiveLocals;
var negativeLocals = adjacentLocalsToLocal.NegativeLocals;
var positiveslocalsRepeated = positiveLocals.Intersect(localDto.PositivesLocalsDtos);
positiveLocals.RemoveAll(x => positiveslocalsRepeated.Contains(x));
var negativeslocalsRepeated = negativeLocals.Intersect(localDto.NegativesLocalsDtos);
negativeLocals.RemoveAll(x => negativeslocalsRepeated.Contains(x));
localDto.PositivesLocalsDtos = new List<LocalDto>(positiveLocals);
localDto.NegativesLocalsDtos = new List<LocalDto>(negativeLocals);
return TryUpdateLocalFromLocalDto(localDto.Id, localDto);
}
private bool TryUpdateLocalFromLocalDto(int idLocal, LocalDto localDto)
{
var local = _localServices.GetById(idLocal);
local.PositivesLocals.Clear();
local.NegativesLocals.Clear();
_localServices.Update(local);
if (local != null)
{
localDto.Id = idLocal;
var localUpdated = _mappingServices.Map(localDto, local);
_localServices.Update(localUpdated);
return true;
}
return false;
}
******** LocalDto *************
public class LocalDto
{
public int Id { get; set; }
public string Number { get; set; }
public float Volumen { get; set; }
public int NumberMaxPeople { get; set; }
public SectionDto SectionDto { get; set; }
public List<LocalDto> PositivesLocalsDtos { get; set; }
public List<LocalDto> NegativesLocalsDtos { get; set; }
}
我正在使用ASP.NET WEB API理念,这就是为什么我用JSON(正确)传递相邻位置的列表,因为我认为列表中的对象与之间的关系数据库记录丢失了,但我不明白为什么,因为这些本地DTO正确映射并返回相应的本地对象。但是,当我更新一个本地没有任何正面或负面的本地列表,没有问题..所以我认为这个问题是与自我多对多的关系。
我已经多次跟踪代码,我检查所有实体是否都有关系,一切似乎都没问题,但是当我尝试更新本地实体时插入邻接本地(正本和负本地)给我的错误是我上面提到过。所以我 。我等待你的回答。退休
答案 0 :(得分:0)
我认为正在发生的是以下某些实体实体框架,当您使用automapper服务时,它不会链接数据库中的现有部分,因此我建议您在Dto中不使用其他dto的关系,例如:
public class LocalDto
{ public int Id {get;组; }
public string Number { get; set; }
public float Volumen { get; set; }
public int NumberMaxPeople { get; set; }
public SectionDto SectionDto { get; set; }
public List<LocalDto> PositivesLocalsDtos { get; set; }
public List<LocalDto> NegativesLocalsDtos { get; set; }
}
将其更改为:
public class LocalDto
{ public int Id {get;组; }
public string Number { get; set; }
public float Volumen { get; set; }
public int NumberMaxPeople { get; set; }
public int SectionId { get; set; }
public List<LocalDto> PositivesLocalsDtos { get; set; }
public List<LocalDto> NegativesLocalsDtos { get; set; }
}
并且您还必须更改与这些实体关联的映射器,这必须从LocalMappers类中删除,
.ForMember(localDto => localDto.SectionDto, mc => mc.MapFrom(local => local.Section));
此解决方案适用于所有具有关系的Dtos,将它们与与之相关的实体的ID链接,而不是与Dtos相关联 我希望我帮助了