【问题标题】:Mapper Dto to Entity in EF using self many to many relationship使用自我多对多关系将 Dto 映射到 EF 中的实体
【发布时间】:2018-02-27 22:25:01
【问题描述】:

我有一个项目有 4 个类:Direction、Area、Section 和 Local。方向有很多区域,区域有很多部分,部分有很多当地人。本地有正本地和负本地,因此本地实体将具有自身的多对多关系。我正在使用 Automapper 将 LocalDto 转换为本地,但是当我尝试使用插入的正本地和/或负本地更新此实体时,系统会生成此异常:

操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

所以,它们是我的实体的映射器类:

*******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);
    }
}

********区域映射器**********

  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 被正确映射并返回相应的本地对象。但是,当我在没有任何正面或负面当地人列表的情况下更新本地人时,没问题..所以我认为问题在于自我多对多关系。

我已经多次跟踪代码,我检查是否所有实体都有它们的关系并且一切似乎都很好,但是当我尝试更新插入相邻本地的本地实体(正和负本地)给我的错误是我上面提到过。所以我 。我等待你的回答。问候

【问题讨论】:

    标签: asp.net .net entity-framework automapper


    【解决方案1】:

    我认为正在发生的事情是以下一些实体实体框架,当您使用 automapper 服务时,它没有链接数据库中的现有部分,所以我建议在您的 Dto 中不要使用其他 dto 的关系,因为示例:

    public class LocalDto
    

    { 公共 int ID { 获取;放; }

    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
    

    { 公共 int ID { 获取;放; }

    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));
    

    此解决方案适用于所有具有关系的 Dto,将它们链接到与其相关的实体的 ID,而不是与 Dto 希望对您有所帮助

    【讨论】:

    • 嗨,我按照你说的做了,但是当我尝试将相邻的本地人添加到 LocalDto 时,我一直给出同样的错误......我还能做什么:(
    猜你喜欢
    • 2020-06-01
    • 2019-01-14
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多