AutoMapper ProjectTo not returning navigation properties - automapper

ProjectTo works fine when entities have navigation properties and matching properties on corresponding Dtos. what am i missing ?
in my case this does not work although the query has all data :
public class Category {
....
some properties
...
public Category ParentCategory {get; set;}
}
here is the Dto
public class CategoryDto : IMapFrom<Category>
{
public void Mapping(Profile profile)
{
profile.CreateMap().ReverseMap();
}
....
some properties
...
public CategoryDto ParentCategory {get; set;}
}

Related

Entity Framework Core 2.1 : The specified field 'Model' could not be found for property 'Model' on entity type 'BarCodeDevice'

I need to use Code First approach to generate Database by Entity Framework Core 2.1 but I get this error:
The specified field 'Model' could not be found for property 'Model' on entity type 'BarCodeDevice'.
Here are the classes I have used to do so
public class BarCodeDevice
{
public int SerialNumber { get; set; }
public string Model { get; set; }
public virtual ICollection<ClientBarCodeDevice> ClientBarCodeDeviceList { get; set; }
}
And the configuration class
public class BarCodeDeviceConfiguration : IEntityTypeConfiguration<BarCodeDevice>
{
public void Configure(EntityTypeBuilder<BarCodeDevice> builder)
{
builder.HasKey(x => x.SerialNumber);
builder.Property(t => t.Model)
.IsRequired()
.HasField("Model");
}
}
And The DbContext Class
public class SegregationDbContext : DbContext, IDisposable
{
public SegregationDbContext(DbContextOptions<SegregationDbContext> options) : base(options)
{ }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new BarCodeDeviceConfiguration());
}
public DbSet<BarCodeDevice> BarCodeDevices { get; set; }
}
And finally the configuration
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SegregationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default")));
services.AddMvc();
}
The problem is this fluent configuration line:
.HasField("Model")
HasField is used to specify the backing field for the property being configured, when the backing field name does not conform to the conventions.
But you Model property is auto property and there is no backing field called Model, hence the exception.
So either remove that line, e.g.
builder.Property(t => t.Model)
.IsRequired();
or if you want to force using the backing field with unknown name (which is the case with auto properties), use UsePropertyAccessMode method instead, e.g.
builder.Property(t => t.Model)
.IsRequired()
.UsePropertyAccessMode(PropertyAccessMode.Field);

Mapping int (Id) to Model instance

I often have Models and Dtos like this:
// DTO class
public class OrderDto
{
public int Id { get; set; }
public DateTime Date { get set; }
public int ProductId { get; set; }
// ...
}
// Model class
public class Order : BaseObject
{
public DateTime Date { get set; }
public Product Product { get; set; }
// ...
}
// Model class
public class Product : BaseObject
{
// ...
}
In order to map my OrderDto to the Order class I have to configure AutoMapper for this particular "association" like so:
CreateMap<OrderDto, Order>()
.ForMember(m => m.Product, d => d.ResolveUsing((d, m) =>
{
return m.Session.GetObjectByKey<Product>(dto.ProductId);
}))
This is quite cumbersome to do this for each case like this. Therefore I was looking into generalizing this behaviour by using a custom TypeConverter class:
public class IntBaseObjectTypeConverter : ITypeConverter<int, BaseObject>
{
private UnitOfWork uow;
// ...
public BaseObjectConvert(int source, BaseObject destination, ResolutionContext context)
{
return uow.Session.GetObjectByKey(typeof(destination), source);
}
}
However, this will fail of course if the destination is null. Unfortunately the ResolutionContext does not give me any clue about the specific type of the destination property.
Now my question is, if there is another way to achieve with AutoMapper what I would like to do?
Please note that I am not using Entity Framework which of course would solve this issue on the model level with foreign key and navigational properties. I use XPO from DevExpress which does not allow foreign key and navigational properties like in Entity Framework.

how to desactivate lazy loading for entity framework 6

public class Country : Item
{
public string Code
{get; set;}
public string CodePhone
{ get; set; }
public string Name
{get; set;}
public string Flag
{ get; set; }
public decimal? Latitude
{get; set;}
public decimal? Longitude
{get; set;}
public int RegionsCount
{get; set;}
[ForeignKey("DefaultCurrency")]
public int? DefaultCurrencyID
{get; set;}
public virtual Currency DefaultCurrency
{ get; set; }
public ContinentType ContinentType
{ get; set; }
public virtual ICollection<Property>
Properties
{get; set;}
public ICollection<CountryLocale>
CountryLocales
{ get; set; }
}
public class CountryLocale : ItemLocale
{
[ForeignKey("Country")]
public int CountryID
{get; set;}
public Country
Country
{get; set;}
public string FullName
{get;set;}
}
public TEntity Get(Expression<Func<TEntity, bool>> where, params string[] includes)
{
var model = this.DbSet;
foreach (var property in includes)
{
model.AsExpandable().Include(property);
}
return model.Where(where).FirstOrDefault();
}
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
Country country = this._CountryRepository.Get(p=>p.ID == this.CountryID, new string[] { "CountryLocales" });
Value cannot be null.
Parameter name: source
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentNullException: Value cannot be null.
Parameter name: source
line : CountryLocale countrylo = country.CountryLocales.First();
i got this error when trying to desactivate lazyloading for performance reasons. how can i resolve the problem? thanks in advance.
As you disabled LazyLoading you need to manually load the child properties of your main object with Include
var country = db.Country.Include("CountryLocales");
The other way around would be:
Dont disable lazy load and use include in your queries.
Try including your child objects one by one until you feel the
performance is better.
Usually if you know you will iterate over a
child object you should use include in your query for that child
object.
remeber to include second level child if you need to access a property of that level... Include("Parent.Child")

emitmapper circular reference

emit mapper circular reference issues. I am trying to map AA to A. A has object of B, but B has object of A. This is circular reference issue. I am not sure how Emit mapper can handle this issue.
public class A
{
public A()
{
list = new List<B>();
}
List<B> list {get; set;}
}
public class B
{
public A object {get; set;}
}
public class AA
{
public AA()
{
list= new List<BB>();
}
public List<BB> list {get; set;}
}
public class BB
{
public AA object {get; set;}
}
objectified = new A();
ObjectMapperManager.DefaultInstance.Get Mapper<A, AA>().Map(objectified);
Need to map from A to AA. Now I got the stack overflow error. Any one know how to resolve this issue?
The circular reference classes are created by EF power tools. And the generated classes need to be updated to one way parent-reference only class. So the issue is not related to the Emitmapper, the issue is the class design itself.
public class A
{
public A()
{
list = new List<B>();
}
List<B> list {get; set;}
}
public class B
{
//remove the following child-parent relationship.
//public A object {get; set;}
}

Does mapping a child class in EF 4.1 require an ID property?

I am starting to move some code over to EF4.1 and I am having a problem loading child classes.
I found this article and it looks like there's a way to map the child class but I was wondering if the ID columns in the parent class are required.
I thought it was "no code" to simply include a reference to the child class and the rest was taken care of.
Here's the current object model:
public class classMember
{
public int MemberID {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
}
public class classReservation
{
public int ReservationID {get; set;}
public classMember Member {get; set;}
}
But loading the classReservation just gives null Members.
Do I need to include a property for the MemberID in classReservation as well as in classMember? It seems redundant from a design point of view.
First of all, in order to have navigation properties from one entity to another, they must be declared as virtual in your POCO. So you would want this:
public class classReservation
{
public int ReservationID {get; set;}
public virtual classMember Member {get; set;}
}
This is because at runtime, EF actually subclasses your POCO using reflection. To make the navigation property work, it needs to be able to override it. This is why it has to be virtual.
To answer your second question, no, you do not need to have a "foreign key property" from the child entity to the parent entity. It helps EF, but is not necessary.
We are in the process of removing foreign key properties from our entity models. To do it, you still need to tell EF how to map the relationship in the db. This can be done in your DbContext class' OnModelCreating method:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<classReservation>
.HasRequired(r => r.classMember)
.WithMany()
.Map(x => x.MapKey("MemberId"));
}
You could also use HasOptional, WithRequiredDependent, etc, depending on the cardinality and multiplicity of the relationship.

Resources