title: AutoMapper + nullable foreign key + Entity Framework Core
body: <p><strong>Status Update (12/19/18)</strong></p>
  
  <p>The problem is that when <code>Map&lt;Product&gt;(cmd)</code> executes, AutoMapper maps a new <code>Color</code> type (with null values) to <strong>Product</strong>.</p>
  
  <hr />
  
  <p><strong>Question:</strong><br>
  Could this be a bug when AutoMapper tries to “flatten’ the <code>ColorSystemName</code> member?</p>
  
  <hr />
  
  <p><strong>ProductCmd.cs</strong>  </p>
  
  <pre><code>public class ProductCmd
  {
      public virtual int? ColorId { get; set; }
      public virtual ColorCmd Color { get; set; }
      public virtual string ColorSystemName { get; set; }
  }
  </code></pre>
  
  <p>I found this by removing the <code>Color</code> navigation property from <strong>Product</strong> and <strong>ProductCmd</strong> and executing <code>AssertConfigurationIsValid</code>:</p>
  
  <p><strong>Startup.cs</strong></p>
  
  <pre><code>public class Startup
  {
      public void Configure(IApplicationBuilder app, 
                            IHostingEnvironment env, 
                            IMapper autoMapper)
      {
          autoMapper.ConfigurationProvider.AssertConfigurationIsValid();
      }
  }
  </code></pre>
  
  <p>Now, I get:</p>
  
  <blockquote>
    <p>AutoMapper.AutoMapperConfigurationException<br>
    HResult=0x80131500<br>
    Source=AutoMapper<br>
    StackTrace:  Cannot evaluate the exception stack trace</p>
    
    <p>‘AutoMapperConfigurationException: Unmapped members were
    found’.</p>
  </blockquote>
  
  <p>This problem does not occur when I remove the <code>ColorSystemName</code> member:</p>
  
  <p><strong>ProductCmd.cs</strong></p>
  
  <pre><code>public class ProductCmd
  {
      public virtual int? ColorId { get; set; }
      public virtual ColorCmd Color { get; set; }
  }
  </code></pre>
  
  <hr />
  
  <p><strong>Question:</strong><br>
  Did AutoMapper instantiate a new <strong>Color</strong> type while trying to flatten <code>ColorSystemName</code> in the original configuration which contained a null <code>Color</code> navigation property?</p>
  
  <hr />
  
  <p><strong>Original Post</strong></p>
  
  <p>I want AutoMapper to map a null (EF Core navigation) property <code>Color</code> from <code>ProductCmd</code> to <code>Product</code>.</p>
  
  <p>I have tried using a single navigation property as well as a fully-defined relationship (including an inverse navigation property). </p>
  
  <p><strong>Product.cs</strong></p>
  
  <pre><code>public class Product
  {
      public virtual int? ColorId { get; set; }
      public virtual Color Color { get; set; }
  }
  </code></pre>
  
  <p><strong>ProductCmd.cs</strong></p>
  
  <pre><code>public class ProductCmd
  {
      public virtual int? ColorId { get; set; }
      public virtual ColorCmd Color { get; set; }
      public virtual string ColorSystemName { get; set; }
  }
  </code></pre>
  
  <p><strong>Color.cs</strong></p>
  
  <pre><code>public class Color
  {
      public virtual int Id { get; set; }
      public virtual string SystemName { get; set; }
  }
  </code></pre>
  
  <p><strong>ColorCmd.cs</strong></p>
  
  <pre><code>public class ColorCmd
  {
      public virtual int Id { get; set; }
      public virtual string SystemName { get; set; }
  }
  </code></pre>
  
  <p><strong>ProductTypeConfiguration.cs</strong></p>
  
  <pre><code>public class ProductTypeConfiguration : IEntityTypeConfiguration&lt;Product&gt;
  {
      public void Configure(EntityTypeBuilder&lt;Product&gt; builder)
      {
          builder.ToTable("Product", "dbo");
          builder.HasKey(a =&gt; a.Id);
          builder.HasOne(a =&gt; a.Color)
                 .WithMany()
                 .HasForeignKey(s =&gt; s.ColorId)
                 .OnDelete(DeleteBehavior.ClientSetNull)
                 .IsRequired(false);
      }
  }
  </code></pre>
  
  <p><strong>ColorTypeConfiguration.cs</strong></p>
  
  <pre><code>public class ColorTypeConfiguration : IEntityTypeConfiguration&lt;Color&gt;
  {
      public void Configure(EntityTypeBuilder&lt;Color&gt; builder)
      {
          builder.ToTable("Color", "dbo");
          builder.HasKey(a =&gt; a.Id);
      }
  }
  </code></pre>
  
  <p><strong>InitialInventoryDbMigration.cs</strong></p>
  
  <pre><code>public partial class InitialInventoryDbMigration : Migration
  {
      protected override void Up(MigrationBuilder migrationBuilder)
      {
          migrationBuilder.CreateTable(
              name: "Color",
              schema: "dbo",
              columns: table =&gt; new
              {
                  Id = table.Column&lt;int&gt;(nullable: false)
                      .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                  SystemName = table.Column&lt;string&gt;(maxLength: 256, nullable: false),
              },
              constraints: table =&gt;
              {
                  table.PrimaryKey("PK_Color", x =&gt; x.Id);
              });
  
          migrationBuilder.CreateTable(
              name: " Product",
              schema: "dbo",
              columns: table =&gt; new
              {
                  Id = table.Column&lt;int&gt;(nullable: false)
                      .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                  ColorId = table.Column&lt;int&gt;(nullable: true),
              },
              constraints: table =&gt;
              {
                  table.PrimaryKey("PK_ Product", x =&gt; x.Id);
                  table.ForeignKey(
                      name: "FK_Product_Color_ColorId",
                      column: x =&gt; x.ColorId,
                      principalSchema: "dbo",
                      principalTable: " Color",
                      principalColumn: "Id",
                      onDelete: ReferentialAction.Restrict);
              });
  
      }
  </code></pre>
  
  <p><strong>Startup.cs</strong></p>
  
  <pre><code>public class Startup
  {
      public IServiceProvider ConfigureServices(IServiceCollection services)
      {
          _services.AddAutoMapper(cfg =&gt;
              {
                  cfg.AllowNullDestinationValues = true;
              },
              new[] 
                      typeof(AutoMapperProfiles_Inventory)
              });
      }
  }
  </code></pre>
  
  <p><strong>AutoMapperProfiles_Inventory.cs</strong></p>
  
  <pre><code>public class AutoMapperProfiles_Inventory
  {
      public List&lt;Profile&gt; GetProfiles()
      {
          var profiles = new List&lt;Profile&gt;()
          {
              new AutoMapperProfile_Inventory_Cmd()
          };
          return profiles;
      }
  }
  </code></pre>
  
  <p><strong>AutoMapperProfile_Inventory_Cmd.cs</strong></p>
  
  <pre><code>using features = Module.Inventory.ApplicationCore.BLL.Domain.Features;
  using pocos = Module.Inventory.ApplicationCore.BLL.Domain.Entities;
  using AutoMapper;
  
  namespace Dcs.NetCore.Module.Inventory.ApplicationCore.BLL.Domain.Entities.Mappers.Profiles
  {
      public class AutoMapperProfile_Inventory_Cmd : Profile
      {
          public AutoMapperProfile_Inventory_Cmd()
          {
              CreateMap&lt;pocos.Color, features.Colors.Cmd&gt;().ReverseMap();
              CreateMap&lt;pocos.Product, features.Products.Cmd&gt;()
              .ReverseMap();
          }
      }
  }
  </code></pre>
  
  <p>Libraries utilized:</p>
  
  <blockquote>
    <ul>
    <li>Microsoft.EntityFrameworkCore v.2.1.4</li>
    <li>Microsoft.NETCore.App v.2.1</li>
    <li>AutoMapper.Extensions.Microsoft.DependencyInjection v.6.0.0</li>
    <li>AutoMapper v.8.0.0</li>
    </ul>
  </blockquote>
  
  <p>Problem also occurs with:</p>
  
  <blockquote>
    <ul>
    <li>AutoMapper.Extensions.Microsoft.DependencyInjection v.5.0.1</li>
    <li>AutoMapper v.7.0.1</li>
    </ul>
  </blockquote>
  
  <p>I could not find a solution to this scenario in <a href="https://media.readthedocs.org/pdf/automapper/latest/automapper.pdf" rel="nofollow noreferrer">AutoMapper Documentation</a> or various online resources.</p>
  
  <p>Here is sample code showing the mapping results and error:</p>
  
  <pre><code>public class Example
  {
      private readonly IMapper _mapper;
      private readonly IProductRepository _repository;
  
      public Example(IMapper mapper, IProductRepository repository)
      {
          _mapper = mapper;
          _repository = repository;
      }
  
      public void Add()
      {
          var cmd = new Cmd()
          {
              Color = null,
              ColorId = null,
              Id = 0,
              ProductBrand = null,
              ProductBrandId = 2
          };
  
          var dao = _mapper.Map&lt;Product&gt;(cmd);
          //
          //
          // at this point:
          //
          //
          // dao.Color == Color(with null values)
          // dao.Color.Id == 0
          // dao.ColorId == null
          // dao.Id == 0
          // dao.ProductBrand == ProductBrand(with null values)
          // dao.ProductBrand.Id == 0
          // dao.ProductBrandId == 1
          //
          //
          _repository.AddAsync(dao);
          //
          // executes dbSet.Add(dao);
          //
          //
          // at this point:
          //
          // dao.Color == Color(with null values)
          // dao.Color.Id == -2147482643
          // dao.ColorId == -2147482643
          // dao.Color.Products[0].Color.Id == -2147482643
          // dao.Color.Products[0].Id == -2147482647
          // dao.Id == -2147482647
          // dao.ProductBrand == ProductBrand(with correct values)
          // dao.ProductBrand.Id == 1
          // dao.ProductBrandId == 1
          // 
          //
          _repository.SaveChangesAsync();
          //
          // executes _dbContext.SaveChangesAsync();
          //
          //
          // at this point:
          //
          // System.Data.SqlClient.SqlException(0x80131904): 
          // "Cannot insert the value NULL into column 'AddedBy', 
          // table 'dbo.Color'; 
          // column does not allow nulls. 
          // INSERT fails.\r\nThe statement has been terminated."            
          //
      }
  </code></pre>
  
  <p>}</p>