开发者

Map only changed properties?

Using AutoMapper, is it possible to map only the changed properties from the View Model to the Domain Object?

The problem I am coming across is that if there are properties on the View Model that are not ch开发者_JS百科anged (null), then they are overwriting the Domain Objects and getting persisted to the database.


Yes, it can be done, but you have to specify when to skip the destination property using Condition() in your mapping configuration.

Here's an example. Consider the following classes:

public class Source
{
    public string Text { get; set; }
    public bool Map { get; set; }
}

public class Destination
{
    public string Text { get; set; }
}

The first map won't overwrite destination.Text, but the second will.

Mapper.CreateMap<Source, Destination>()
            .ForMember(dest => dest.Text, opt => opt.Condition(src => src.Map));

var source = new Source { Text = "Do not map", Map = false };
var destination = new Destination { Text = "Leave me alone" };
Mapper.Map(source, destination);
source.Map = true;
var destination2 = new Destination { Text = "I'll be overwritten" };
Mapper.Map(source, destination2);


@Matthew Steven Monkan is correct, but seems AutoMapper changed API. I will put new one for others refer.

public static IMappingExpression<TSource, TDestination> MapOnlyIfChanged<TSource, TDestination>(this IMappingExpression<TSource, TDestination> map)
    {
        map.ForAllMembers(source =>
        {
            source.Condition((sourceObject, destObject, sourceProperty, destProperty) =>
            {
                if (sourceProperty == null)
                    return !(destProperty == null);
                return !sourceProperty.Equals(destProperty);
            });
        });
        return map;
    }

that's all


For Automapper version < 6.0

Yes; I wrote this extension method to map only dirty values from a model to Entity Framework.

public static IMappingExpression<TSource, TDestination> MapOnlyIfDirty<TSource, TDestination>(
    this IMappingExpression<TSource, TDestination> map)
{
    map.ForAllMembers(source =>
    {
        source.Condition(resolutionContext =>
        {
            if (resolutionContext.SourceValue == null)
                return !(resolutionContext.DestinationValue == null);
            return !resolutionContext.SourceValue.Equals(resolutionContext.DestinationValue);
        });
    });
    return map;
}

Example:

Mapper.CreateMap<Model, Domain>().MapOnlyIfDirty();


No.

This is exactly one of the reasons you never map from viewmodel to domain model. Domain/business model changes are too important for a tool to handle.

Automapper is not designed to handle this scenario:

AutoMapper works because it enforces a convention. It assumes that your destination types are a subset of the source type. It assumes that everything on your destination type is meant to be mapped. It assumes that the destination member names follow the exact name of the source type. It assumes that you want to flatten complex models into simple ones.

From: https://jimmybogard.com/automappers-design-philosophy/


Manually:

customer.LastName = viewModel.LastName

Changing business state is too important to do otherwise.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜