Skip to content

Instantly share code, notes, and snippets.

@MrZander
Last active March 22, 2023 16:36
Show Gist options
  • Save MrZander/0bcdd5a9b8b42e862b5b523b0d49002a to your computer and use it in GitHub Desktop.
Save MrZander/0bcdd5a9b8b42e862b5b523b0d49002a to your computer and use it in GitHub Desktop.
AutoMapper ProjectTo error repro
using AutoMapper;
using Microsoft.EntityFrameworkCore;
namespace MapRepro
{
internal class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new TestProfile());
});
config.AssertConfigurationIsValid();
var mapper = config.CreateMapper();
var context = new ClientContext(new DbContextOptionsBuilder<ClientContext>().UseInMemoryDatabase("Test").Options);
SeedContext(context);
// Bar -> Baz -> Widgets.FirstOrDefault()
// OKAY
var resultOkay = mapper.ProjectTo<Models.BarModel>(context.Bars);
System.Diagnostics.Debug.Assert(resultOkay.First().MyBaz.FirstWidget.Id == 50);
// Foo -> Bar -> Baz -> Widgets.FirstOrDefault()
// System.ArgumentException: 'Property 'MapRepro.Entities.Bar Bar' is not defined for type 'MapRepro.Entities.Bar' (Parameter 'property')'
var resultNotOkay = mapper.ProjectTo<Models.FooModel>(context.Foos);
System.Diagnostics.Debug.Assert(resultNotOkay.First().MyBar.MyBaz.FirstWidget.Id == 50);
}
static void SeedContext(ClientContext context)
{
var testBaz = new Entities.Baz() { Id = 1 };
testBaz.Widgets.Add(new Entities.Widget() { Id = 50 });
testBaz.Widgets.Add(new Entities.Widget() { Id = 60 });
var testBar = new Entities.Bar() { Id = 100 };
testBar.Foos.Add(new Entities.Foo() { Id = 200 });
testBaz.Bars.Add(testBar);
context.Bazs.Add(testBaz);
context.SaveChanges();
}
}
class TestProfile : Profile
{
public TestProfile()
{
CreateMap<Entities.Foo, Models.FooModel>()
.ForMember(f => f.MyBar, opts => opts.MapFrom(src => src.Bar))
;
CreateMap<Entities.Bar, Models.BarModel>()
.ForMember(f => f.MyBaz, opts => opts.MapFrom(src => src.Baz))
;
CreateMap<Entities.Baz, Models.BazModel>()
.ForMember(f => f.FirstWidget, opts => opts.MapFrom(src => src.Widgets.FirstOrDefault()))
;
CreateMap<Entities.Widget, Models.WidgetModel>();
}
}
class ClientContext : DbContext
{
public ClientContext()
{
}
public ClientContext(DbContextOptions<ClientContext> options)
: base(options)
{
}
public virtual DbSet<Entities.Foo> Foos { get; set; }
public virtual DbSet<Entities.Bar> Bars { get; set; }
public virtual DbSet<Entities.Baz> Bazs { get; set; }
public virtual DbSet<Entities.Widget> Widgets { get; set; }
}
}
namespace MapRepro.Entities
{
public class Foo
{
public int Id { get; set; }
public int BarId { get; set; }
public virtual Bar Bar { get; set; }
}
public class Bar
{
public Bar()
{
Foos = new HashSet<Foo>();
}
public int Id { get; set; }
public int BazId { get; set; }
public virtual Baz Baz { get; set; }
public virtual ICollection<Foo> Foos { get; set; }
}
public class Baz
{
public Baz()
{
Bars = new HashSet<Bar>();
Widgets = new HashSet<Widget>();
}
public int Id { get; set; }
public virtual ICollection<Bar> Bars { get; set; }
public virtual ICollection<Widget> Widgets { get; set; }
}
public partial class Widget
{
public int Id { get; set; }
public int BazId { get; set; }
public virtual Baz Baz { get; set; }
}
}
namespace MapRepro.Models
{
public class FooModel
{
public int Id { get; set; }
public int BarId { get; set; }
public BarModel MyBar { get; set; }
}
public class BarModel
{
public int Id { get; set; }
public int BazId { get; set; }
public BazModel MyBaz { get; set; }
}
public class BazModel
{
public int Id { get; set; }
public WidgetModel FirstWidget { get; set; }
}
public class WidgetModel
{
public int Id { get; set; }
public int BazId { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment