Bỏ qua ánh xạ một thuộc tính với Automapper


285

Tôi đang sử dụng Automapper và tôi có kịch bản sau: Class OrderModel có một thuộc tính được gọi là 'ProductName' không có trong cơ sở dữ liệu. Vì vậy, khi tôi cố gắng thực hiện ánh xạ với:

Mapper.CreateMap<OrderModel, Orders>(); 

Nó tạo ra một ngoại lệ:

"1 thuộc tính sau trên Project.ViewModels.OrderModel không được ánh xạ: 'ProductName'

Tôi đã đọc tại Wiki của AutoMapper về Dự đoán trường hợp ngược lại (thuộc tính bổ sung nằm ở đích chứ không phải trong nguồn thực sự là trường hợp của tôi)

Làm cách nào tôi có thể tránh máy tự động để tạo bản đồ của tài sản này?


7
Automapper không hoạt động theo cách đó. Nó chỉ quan tâm đến các thuộc tính trên các đối tượng đích. Src có thể chứa 100 thuộc tính bổ sung - Automapper chỉ ánh xạ các thuộc tính Dest. Phải có một cái gì đó khác gây ra ngoại lệ ánh xạ. Bạn có thể gửi một số mã của những gì không hoạt động?
PatrickSteele

Nó làm những gì bạn yêu cầu tự động. Đăng một số mã để làm rõ
BeRecursive

Hãy xem các bài viết sau, những bài viết này có thể giúp bạn stackoverflow.com/questions/4456519/ nam stackoverflow.com/questions/4052579/
trộm

3
@Patrick AutoMapper thực hiện một số thủ thuật với việc phân tích tên phương thức / thuộc tính. Có thể có một tài sản trên nguồn đang được lập bản đồ một cách vô tình ngay cả khi không có kết quả khớp chính xác ở đích đến. Đây là lý do tại sao có ForSourceMember (... Bỏ qua ()) để ngăn chặn điều này khi nó xảy ra.
AaronLS

Câu trả lời:


477

Từ Jimmy Bogard: CreateMap<Foo, Bar>().ForMember(x => x.Blarg, opt => opt.Ignore());

Đó là một trong những bình luận tại blog của anh ấy .


13
Ngoài ra, CreateMap<Foo, Bar>().ForSourceMember(x => x.Blarg, opt => opt.Ignore());có thể hữu ích
stackoverfloweth

5
@stackoverfloweth Ý bạn là : CreateMap<SourceType, DestType> (MemberList.Source).ForSourceMember(x => x.MySourceProperty, opt => opt.DoNotValidate())?
monty

12
Bỏ qua đã được thay thế bằng DoNotValidate trong ForSourceMember: github.com/AutoMapper/AutoMapper/blob/master/docs/
Jamie

@Jamie @monty - Tôi đã bắt đầu cập nhật lại: bình luận của bạn, nhưng có vẻ như thay đổi cú pháp chỉ ảnh hưởng đến trường hợp chiếu (trong đó thuộc tính nguồn cần phải bỏ qua). Yêu cầu của OP là bỏ qua một thuộc tính đích, do đó, Ignore()vẫn là cú pháp chính xác. Điều này là do thay đổi cú pháp Ignoređược thực hiện trên ISourceMemberConfigurationExpressiongiao diện nhưng không phải trên IMemberConfigurationExpression`3giao diện rời rạc .
smartcaveman

2
@Franva ForMember () thực sự là "ForDestinationMember ()"
rvnlord

243

Tôi có lẽ là một người cầu toàn; Tôi thực sự không thích cú pháp ForMember (..., x => x.Ignore ()). Đó là một điều nhỏ, nhưng nó quan trọng với tôi. Tôi đã viết phương thức mở rộng này để làm cho nó đẹp hơn một chút:

public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(
    this IMappingExpression<TSource, TDestination> map,
    Expression<Func<TDestination, object>> selector)
{
    map.ForMember(selector, config => config.Ignore());
    return map;
}

Nó có thể được sử dụng như vậy:

Mapper.CreateMap<JsonRecord, DatabaseRecord>()
        .Ignore(record => record.Field)
        .Ignore(record => record.AnotherField)
        .Ignore(record => record.Etc);

Bạn cũng có thể viết lại để làm việc với nó params, nhưng tôi không thích giao diện của một phương thức với vô số lambdas.


6
Tôi biết điều này vượt xa câu hỏi ban đầu nhưng tôi thực sự thích câu trả lời này, nó sạch sẽ, rất dễ đọc và dễ hiểu ngay lập tức cộng với dễ sử dụng lại
Lski

Về params: Bạn có thể trả về một loạt các bộ chọn từ bên trong một lambda, sau đó ánh xạ qua từng bộ chọn với foreachhoặc có Select()lẽ trông không lộn xộn hơn.
jpaugh

cảm ơn @Steve Rukuts, vì bất kỳ ai đang tìm kiếm phương thức mở rộng để bỏ qua các thành viên nguồn, bạn có thể sử dụng IMapsExpression <TSource, TDestination> IgnoreSourceValidation <TSource, TDestination> này (bản đồ IMapsExpression <TSource, TDestination> , đối tượng >> bộ chọn) {map.ForSourceMember (bộ chọn, cấu hình => config.DoNotValidate ()); trả lại bản đồ; }
Jason Dias

79

Bạn có thể làm được việc này:

conf.CreateMap<SourceType, DestinationType>()
   .ForSourceMember(x => x.SourceProperty, y => y.Ignore());

Máy tự động có tiện ích mở rộng ForSourceMember không?
Được đổi

Tôi làm điều này hiện tại, nhưng sẽ thật lý tưởng khi KHÔNG phải tạo ra tất cả những điều này ...: /
Tom Stickel

Bạn có biết có cách nào để bỏ qua khi thực sự lập bản đồ không và khi tạo bản đồ?
Sam tôi đang nói Phục hồi lại

FYI: được hợp nhất từ stackoverflow.com/questions/4052579/
Shog9

3
Đối với kịch bản được đưa ra trong câu hỏi, đây phải là câu trả lời được chấp nhận. Câu trả lời được chấp nhận hiện tại bỏ qua ánh xạ các thuộc tính trong đối tượng đích. Câu hỏi này là hỏi về việc bỏ qua ánh xạ trong đối tượng nguồn.
Rob S.

28

Chỉ dành cho bất kỳ ai đang cố gắng thực hiện điều này một cách tự động, bạn có thể sử dụng phương thức tiện ích mở rộng đó để bỏ qua các thuộc tính không tồn tại trên loại đích:

public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var sourceType = typeof(TSource);
    var destinationType = typeof(TDestination);
    var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType)
        && x.DestinationType.Equals(destinationType));
    foreach (var property in existingMaps.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

được sử dụng như sau:

Mapper.CreateMap<SourceType, DestinationType>().IgnoreAllNonExisting();

cảm ơn Can Gencer vì tiền boa :)

nguồn: http://cangencer.wordpress.com/2011/06/08/auto-ignore-non-ex hiện -properies-with-automapper /


3
FYI: được hợp nhất từ stackoverflow.com/questions/4052579/
Shog9

1
Điều này không hoạt động khi tiêm IMapper. Mapper.GetAllTypeMaps không tồn tại trong phiên bản AutoMapper mới nhất. Ngoài ra, khi tôi thiết lập bản đồ của mình trong AutoMapper.Profile và sau đó đã tiêm IMapper, tôi nhận được ngoại lệ này "Mapper không được khởi tạo. Gọi Khởi tạo với cấu hình phù hợp. Nếu bạn đang cố gắng sử dụng các phiên bản của trình ánh xạ thông qua một container hoặc nếu không, hãy chắc chắn rằng bạn không có bất kỳ cuộc gọi nào đến các phương thức Mapper.Map tĩnh và nếu bạn đang sử dụng các phương thức mở rộng ProjectTo hoặc UseAsDataSource, hãy đảm bảo bạn chuyển qua ví dụ IConfigurationProvider thích hợp. "
Ristogod

Tôi chỉ nhận được 'Mapper' does not contain a definition for 'GetAllTypeMaps' [DSSTools]..
Bassie

2
@Bassie Sử dụng Mapper.Configuration.GetAllTypeMaps() nguồn
Mike Bovenlander

28

Hiện tại có (AutoMapper 2.0) một IgnoreMapthuộc tính, mà tôi sẽ sử dụng thay vì cú pháp lưu loát, hơi nặng IMHO.


35
Mặc dù thuộc tính bỏ qua rò rỉ trình ánh xạ tự động thông qua ứng dụng của bạn.
Phill

11
AutoMapper là một thứ mà tôi không ngại rò rỉ khắp nơi. ;)
Pawel Krakowiak

4
Bạn luôn có thể xem xét xuất phát IgnoreMapAttribute.
Alapago

1
Đây là một cách tốt để bỏ qua một thuộc tính cơ sở được kế thừa trên nhiều đối tượng. Tiết kiệm từ việc phải bỏ qua nó trong mọi cấu hình ánh xạ.
Chase Florell

23

Khi ánh xạ mô hình khung nhìn trở lại mô hình miền, có thể đơn giản hơn nhiều khi xác thực danh sách thành viên nguồn thay vì danh sách thành viên đích

Mapper.CreateMap<OrderModel, Orders>(MemberList.Source); 

Bây giờ xác thực ánh xạ của tôi không thất bại, yêu cầu khác Ignore(), mỗi khi tôi thêm một thuộc tính vào lớp miền của mình.


7
Đây là những gì tôi đã tìm kiếm, rất hữu ích khi chỉ sửa đổi một tập hợp con các thuộc tính đối tượng miền từ một DTO đơn giản hơn nhiều.
Adam Tolley

5
Đây là câu trả lời của những đứa trẻ, hãy làm cho chính thức để những người mới sẽ không bị nhầm lẫn
Piotr M

0

Có thể sử dụng IgnoreAttribution trên thuộc tính cần bỏ qua


2
[IgnoreMap]từIgnoreMapAttribute
fiorebat

-5

Xin chào tất cả Xin vui lòng Sử dụng tính năng này hoạt động tốt ... đối với người lập bản đồ tự động sử dụng nhiều .MorMember trong C #

        if (promotionCode.Any())
        {
            Mapper.Reset();
            Mapper.CreateMap<PromotionCode, PromotionCodeEntity>().ForMember(d => d.serverTime, o => o.MapFrom(s => s.promotionCodeId == null ? "date" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", DateTime.UtcNow.AddHours(7.0))))
                .ForMember(d => d.day, p => p.MapFrom(s => s.code != "" ? LeftTime(Convert.ToInt32(s.quantity), Convert.ToString(s.expiryDate), Convert.ToString(DateTime.UtcNow.AddHours(7.0))) : "Day"))
                .ForMember(d => d.subCategoryname, o => o.MapFrom(s => s.subCategoryId == 0 ? "" : Convert.ToString(subCategory.Where(z => z.subCategoryId.Equals(s.subCategoryId)).FirstOrDefault().subCategoryName)))
                .ForMember(d => d.optionalCategoryName, o => o.MapFrom(s => s.optCategoryId == 0 ? "" : Convert.ToString(optionalCategory.Where(z => z.optCategoryId.Equals(s.optCategoryId)).FirstOrDefault().optCategoryName)))
                .ForMember(d => d.logoImg, o => o.MapFrom(s => s.vendorId == 0 ? "" : Convert.ToString(vendorImg.Where(z => z.vendorId.Equals(s.vendorId)).FirstOrDefault().logoImg)))
                .ForMember(d => d.expiryDate, o => o.MapFrom(s => s.expiryDate == null ? "" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", s.expiryDate))); 
            var userPromotionModel = Mapper.Map<List<PromotionCode>, List<PromotionCodeEntity>>(promotionCode);
            return userPromotionModel;
        }
        return null;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.