Create AutoMapper mapping with calculated value? - c#

I'm trying to configure a simple AutoMapper mapping from an Entity Framework entity to a view model object. It mostly works but in the view model I have an int field to hold a count. This field does not exist in the source entity.
cfg.CreateMap<Feed, FeedVM>()
.ForMember(dest => dest.Count, opt => opt.MapFrom(src => src.Orders.Count()));
When I check the validity of the mapping I get the following error message:
The following property on Feed cannot be mapped:
Add a custom mapping expression, ignore, add a custom resolver, or modify the destination type Feed.
Context:
Mapping from type FeedVM to Feed
If I understand the Automapper syntax correctly I am mapping from Feed to FeedVM but the error message seems to indicate that I am mapping from FeedVM to Feed.
What should I be doing to map the value 42 to the Count field in FeedVM?

You should use ResolveUsing:
cfg.CreateMap<Feed, FeedVM>()
.ForMember(dest => dest.Count, opt => opt.ResolveUsing(src => src.Orders.Count()));
Update
John indicates in the comment below that the mappings are correct, the problem lies in a mapping for another entity that is related to Feed. In that entity he is mapping both directions.

Related

Map a member of a member to the current class

I have an EF model with Vehicle.Applications.Warranties, and I'm mapping to VehicleDto. I want the Warranties in VehicleDto and I have a WarrantyDto to receive it. I keep getting null for Warranties, though.
I'm using a projection which might be wrong, but from the AutoMapper docs, I can't see any other way to access IQueryable interfaces like this.
This is what I've tried. Doesn't seem to work.
CreateMap<Vehicle, VehicleDto>();
CreateMap<Warranty, WarrantyDto>();
CreateProjection<Vehicle, VehicleDto>().ForMember(d => d.Warranties, opt => opt.MapFrom(s => s.Applications.Select(a => a.Warranties)))

Update only mapped fields or Ignore the unmapped fields - Automapper?

I'm very new to Automapper and I'm facing difficulties in Updating mapped fields. I must agree that there are millions of answers for this question in internet but the problem is nothing helps for my scenario.
Issue:
I'm trying to update only the mapped fields. But when I do that, my complete destination properties gets updated.
For e.g.,
My destination object(DB Table) holds 5 properties and all the 5
properties accepts null. But I have only 3 properties in my
source(Model file). I'm mapping all the three source fields with the
destination fields but I don't have mapping for the remaining two
destination properties. You would have guessed it correctly, yes when
I update this, that two unmapped fields are also getting update to null(default value - DB). But it
should not be the case, rather it should have the existing values.
Kindly see my code below,
References:
Automapper Version: v6.2.2 and Runtime Version: v4.0.3
Repository.cs,
var objectToUpdate = Mapper.Map<TDomain>(entity); //TDestination Map<TDestination>(object source);
DatabaseContext.Entry(objectToUpdate).State = EntityState.Modified;
InvoiceLineMapping.cs
public static void Map(IProfileExpression profile)
{
profile.CreateMap<Registration, PT_Registration>()
.ForMember(d => d.Name_VC, map => map.MapFrom(s => s.Name))
.ForMember(d => d.UserName_VC, map => map.MapFrom(s => s.Username))
.ForMember(d => d.Mobile_VC, map => map.MapFrom(s => s.Mobile));
}
Note: As I said before, I have two unmapped fields are there in the destination and they are EMail_VC and Comments_VC and their values are sample#test.com and testComments respectively. When update happens, these two fields becomes null(default value)
I tried,
.ForAllOtherMembers(opt => opt.Ignore()); //after the last mapping i.e Mobile
profile.CreateMap(MemberList.Source) // I also tried MemberList.Destination
I also tried, AutoMapper: "Ignore the rest"? extenstion method,
I tried puttin ReverseMap() in the end. //after the last mapping i.e Mobile
I even tried to find the null value and removing from destination object(objectToUpdate - you can see above) but nothing helps.
So can someone please look into this and provide me a better solution. I knew solution would be simpler but as I'm not aware of it, it takes more and more time.
I appreciate your time. Any help would be great helpful.

EF Fluent Mapping not loading all children with eager loading using Include

I've created two entities which are related to each other by joining using three columns, both are views on the database. For the Travel I have the Id, FromCityId and ToCityId, for TravelCost I have the TravelId, FromCityId and ToCityId. The fluent mapping is as below
TravelEntityConfiguration class:
HasMany(x => x.Amounts)
.WithRequired()
.HasForeignKey(x => new
{
x.TravelId,
x.FromCityId,
x.ToCityId
});
and for the travel cost its
TravelCostEntityConfiguration
HasRequired(x => x.Travel)
.WithMany()
.HasForeignKey(x => new
{
x.TravelId,
x.FromCityId,
x.ToCityId
});
When i query these entities and include the navigation property
context.Set<Table>().Include(x => x.TravelCost)....
For each result only the first of the child collection is loaded. I checked the query generated, even the query is correct it returns the full set with all the children and the join is correctly. What am i missing here. Need some help no clue for the moment. basically i suspect the mapping is not correct but didn't found out the problem yet.
Thank you Asad, you lighted up my problem. The problem was with the Id of the TravelCost view which were generated on the fly and ended up to be the same so EF thinks it is the same record, the mapping was totally correct.

AutoMapper mapping Function to a Member's get

I have a Member named "Name" and I'm using AutoMapper to map between my ViewModel and my base Model. However, I also have a method named "GetName()" on a separate ViewModel which seems to be overriding my "Name" member's 'get' on the actual model.
I've since renamed the method to "GetFullName()" and this is no longer a problem.
This work-around works just fine, however, I would like to know what override in AutoMapper I can implement to let it know to not map function values like "GetName()" to a member's 'get'.
You can override via:
Mapper.CreateMap<Foo, FooDto>()
.ForMember(d => d.Name, opt => opt.MapFrom(src => src.Name));

AutoMapper MaxDepth() method

In my project I have a one to many relationship from Client -> Projects. As such, in one of my views, I am trying to show all of the Projects that belong to that Client. So I have an IEnumerable<ProjectDetailsViewModel> that represents all of the clients projects.
The problem is that the ProjectDetailsViewModel has a ClientDetailsViewModel which then has an IEnumerable<ProjectDetailsViewModel> and so on and so forth creating an endless loop of identical entities.
Is this where it is appropriate to use the MaxDepth() method on that .ForMember()? If so, how do I use it in this case, and if not, what is the solution?
I have tried MaxDepth(1) on the Client and whilst this prevents the StackOverflow exception, it then doesn't hold any data in the view model for that client.
The problem was that I explicitly called AutoMapper from with the AutoMapConfig as such:
.ForMember(x => x.Client, opt => opt.MapFrom(src =>
AutoMapper.Mapper.Map<ClientDetailsViewModel>(src.Client)))
If I just define it as:
.ForMember(x => x.Client, opt => opt.MapFrom(src => src.Client))
AutoMapper will know to stop after 1 recursion, and as I already have a map from Client -> ClientDetailsViewModel there is no problem.

Categories

Resources