How to Map (using AutoMapper) entities that have a ForeignKey in ASP.NET CORE 3.1.1 (C#,EntityFrameworkCore)

asp.net-core automapper c# entity-framework-core

Question

I have this function in my controller that creates a an entity:

    [HttpPost]
    [ProducesResponseType(typeof(ConnectionDBResponse), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<ConnectionDBResponse>> PostConnectionDB([FromBody] CreateConnectionDBQuery query)
    {
        var connectionDBs = _mapper.Map<ConnectionDBDataModel>(query);
        _context.ConnectionDB.Add(connectionDBs);
        await _context.SaveChangesAsync();

        var connectionDBResponse = _mapper.Map<ConnectionDBResponse>(connectionDBs);
        return CreatedAtAction(nameof(GetAllConnectionDB), new { id = connectionDBs.Id }, connectionDBResponse);
    }

For that I'm mapping between these two classes: The response Class:

public class CreateConnectionDBQuery
{
    public string ServerType { get; set; }
    public string ServerName { get; set; }
    public string port { get; set; }
    public string AuthType { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public string DBName { get; set; }
    public string FolderName { get; set; }
    public ScheduleConfigResponse ScheduleConfig { get; set; }
    public Boolean hasEmails { get; set; }
    public EmailConfigResponse EmailConfig { get; set; }
}

public class CreateScheduleConfigQuery
{
    public string HourOfSave { get; set; }
    public int NumDaysInDB { get; set; }
    public CreateConnectionDBQuery ConnDB { get; set; }
    public int ConnDBForeignKey { get; set; }
}

public class CreateEmailConfigQuery
{
    public string SuccesEmail { get; set; }
    public string FailureEmail { get; set; }
    public CreateConnectionDBQuery ConnDB { get; set; }
    public int ConnDBForeignKey { get; set; }
}

And the dataModel Class:

[Table("ConnectionDB")]
public class ConnectionDBDataModel
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string ServerType { get; set; }
    [Required]
    public string ServerName { get; set; }
    public string port { get; set; }
    public string AuthType { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    [Required]
    public string DBName { get; set; }
    [Required]
    public string FolderName { get; set; }
    public ScheduleConfigDataModel ScheduleConfig { get; set; }
    public Boolean hasEmails { get; set; }
    public EmailConfigDataModel EmailConfig { get; set; }
}

[Table("ScheduleConfig")]
public class ScheduleConfigDataModel
{
    [Key]
    public int Id { get; set; }
    public string HourOfSave { get; set; }
    public int NumDaysInDB { get; set; }

    public int ConnDBForeignKey { get; set; }
    public ConnectionDBDataModel ConnDB { get; set; }
}

[Table("EmailConfig")]
public class EmailConfigDataModel
{
    [Key]
    public int Id { get; set; }
    public string SuccesEmail { get; set; }
    public string FailureEmail { get; set; }

    public int ConnDBForeignKey { get; set; }
    public ConnectionDBDataModel ConnDB { get; set; }
}

For that I'm using the AutoMapper as following:

        #region ConnectionDB

        CreateMap<ConnectionDBDataModel, ConnectionDBResponse>();

        CreateMap<CreateConnectionDBQuery, ConnectionDBDataModel>()
            .ForMember(dest => dest.Id, opt => opt.Ignore());

        CreateMap<UpdateConnectionDBQuery, ConnectionDBDataModel>()
            .ForMember(dest => dest.Id, opt => opt.Ignore());

        #endregion

        #region ScheduleConfig

        CreateMap<ScheduleConfigDataModel, ScheduleConfigResponse>()
            .ForMember(dest => dest.ConnDBForeignKey, opt => opt.Ignore());

        CreateMap<CreateScheduleConfigQuery, ScheduleConfigDataModel>()
            .ForMember(dest => dest.Id, opt => opt.Ignore())
            .ForMember(dest => dest.ConnDBForeignKey, opt => opt.Ignore());

        CreateMap<UpdateScheduleConfigQuery, ScheduleConfigDataModel>()
            .ForMember(dest => dest.Id, opt => opt.Ignore());

        #endregion ScheduleConfig

        #region EmailConfig

        CreateMap<EmailConfigDataModel, EmailConfigResponse>()
            .ForMember(dest => dest.ConnDBForeignKey, opt => opt.Ignore());

        CreateMap<CreateEmailConfigQuery, EmailConfigDataModel>()
            .ForMember(dest => dest.Id, opt => opt.Ignore())
            .ForMember(dest => dest.ConnDBForeignKey, opt => opt.Ignore());

        CreateMap<UpdateEmailConfigQuery, EmailConfigDataModel>()
            .ForMember(dest => dest.Id, opt => opt.Ignore());

        #endregion

But when I try to create this element it gives me an error saying that it's coming from an invalid Mapping as shown in the screen bellow:

enter image description here

I have tried to Ignore the Foreign Key (because my guess that this problem is coming from the foreignKey) using this line of code : .ForMember(dest => dest.ConnDBForeignKey, opt => opt.Ignore()); , but I guess it's not the way to solve that problem. Any help would be appreciated thank you!

1
-2
4/3/2020 1:13:12 PM

Accepted Answer

The error is happening because when mapping CreateConnectionDBQuery to ConnectionDBDataModel, there is no mapping defined for the types of the ScheduleConfig properties.

I'm guessing that in your CreateConnectionDBQuery, your ScheduleConfig property should be of type CreateScheduleConfigQuery instead of ScheduleConfigResponse.

Alternatively, if you don't want to change the models, you could add a mapping configuration from ScheduleConfigResponse to ScheduleConfigDataModel. But that doesn't seem very intuitive.

1
4/3/2020 1:29:25 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow