Abaikan memetakan satu properti dengan Automapper


285

Saya menggunakan Automapper dan saya memiliki skenario berikut: Class OrderModel memiliki properti yang disebut 'ProductName' yang tidak ada di database. Jadi ketika saya mencoba melakukan pemetaan dengan:

Mapper.CreateMap<OrderModel, Orders>(); 

Ini menghasilkan pengecualian:

"1 properti berikut di Project.ViewModels.OrderModel tidak dipetakan: 'ProductName'

Saya sudah membaca di Wiki untuk Proyeksi AutoMapper kasus sebaliknya (atribut tambahan ada di tujuan, bukan di sumber yang sebenarnya adalah kasus saya)

Bagaimana saya bisa menghindari automapper untuk melakukan pemetaan properti ini?


7
Automapper tidak berfungsi seperti itu. Hanya peduli tentang properti pada objek tujuan. SRC dapat berisi 100 properti tambahan - Automapper hanya memetakan properti dest. Pasti ada sesuatu yang menyebabkan pengecualian pemetaan. Bisakah Anda memposting beberapa kode yang tidak berfungsi?
PatrickSteele

Itu melakukan apa yang Anda minta secara otomatis. Kirimkan beberapa kode untuk diklarifikasi
BeRecursive

Lihatlah tulisan-tulisan berikut, ini mungkin membantu Anda stackoverflow.com/questions/4456519/... stackoverflow.com/questions/4052579/…
Divi

3
@Patrick AutoMapper melakukan beberapa trik dengan menganalisis metode / nama properti. Ada kemungkinan bahwa ada properti di sumber yang sedang dipetakan secara tidak sengaja bahkan jika tidak ada kecocokan persis pada tujuan. Inilah sebabnya mengapa ada ForSourceMember (... Abaikan ()) untuk mencegah hal ini ketika itu terjadi.
AaronLS

Jawaban:


477

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

Itu ada di salah satu komentar di blognya .


13
Juga, CreateMap<Foo, Bar>().ForSourceMember(x => x.Blarg, opt => opt.Ignore());mungkin berguna
stackoverfloweth

5
@stackoverfloweth Do Anda tidak berarti: CreateMap<SourceType, DestType> (MemberList.Source).ForSourceMember(x => x.MySourceProperty, opt => opt.DoNotValidate())?
monty

12
Ignore telah diganti dengan DoNotValidate di ForSourceMember: github.com/AutoMapper/AutoMapper/blob/master/docs/…
Jamie

@Jamie @monty - Saya mulai memperbarui kembali ini: komentar Anda, tetapi sepertinya perubahan sintaks hanya memengaruhi kasus proyeksi (di mana properti sumber perlu diabaikan). Permintaan OP adalah untuk mengabaikan properti tujuan, jadi, Ignore()tetap sintaks yang benar. Ini karena perubahan sintaksis Ignoredibuat pada ISourceMemberConfigurationExpressionantarmuka tetapi tidak pada IMemberConfigurationExpression`3antarmuka terpisah .
smartcaveman

2
@Franva ForMember () sebenarnya "ForDestinationMember ()"
rvnlord

243

Saya mungkin sedikit perfeksionis; Saya tidak terlalu menyukai sintaks ForMember (..., x => x.Ignore ()). Ini hal kecil, tetapi itu penting bagi saya. Saya menulis metode ekstensi ini untuk membuatnya sedikit lebih bagus:

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;
}

Dapat digunakan seperti:

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

Anda juga bisa menulis ulang untuk bekerja params, tapi saya tidak suka tampilan metode dengan banyak lambda.


6
Saya tahu ini melampaui pertanyaan awal tetapi saya sangat suka jawaban ini, bersih, sangat mudah dibaca dan langsung dipahami ditambah mudah digunakan kembali
Lski

Mengenai params: Anda bisa mengembalikan array penyeleksi dari dalam lambda tunggal, lalu memetakan masing-masing pemilih dengan foreachatau Select()Mungkin tampak tidak berantakan.
jpaugh

terima kasih @Steve Rukuts, untuk siapa saja yang mencari metode ekstensi untuk mengabaikan anggota sumber, Anda dapat menggunakan IMappingExpression statis publik ini <TSource, TDestination> IgnoreSourceValidation <TSource, TDestination> (ini IMappingExpression <TSource, TDestination> peta, Ekspresi <Func <TSource , object >> selector) {map.ForSourceMember (pemilih, config => config.DoNotValidate ()); kembali peta; }
Jason Dias

79

Kamu bisa melakukan ini:

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

Apakah automapper memiliki ekstensi ForSourceMember?
Ditebus1

Saya melakukan ini saat ini, tetapi akan ideal untuk TIDAK harus membuat semua ini Abaikan ...: /
Tom Stickel

apakah Anda tahu jika ada cara untuk mengabaikan ketika benar-benar melakukan pemetaan dan bukan saat membuat peta?
Sam saya berkata Reinstate Monica


3
Untuk skenario yang diberikan dalam pertanyaan, ini harus menjadi jawaban yang diterima. Jawaban yang diterima saat ini mengabaikan pemetaan properti di objek tujuan. Pertanyaan ini menanyakan tentang mengabaikan pemetaan di objek sumber.
Rob S.

28

Hanya bagi siapa saja yang mencoba melakukan ini secara otomatis, Anda dapat menggunakan metode ekstensi itu untuk mengabaikan properti yang tidak ada pada jenis tujuan:

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;
}

untuk digunakan sebagai berikut:

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

terima kasih kepada Can Gencer untuk tipnya :)

sumber: http://cangencer.wordpress.com/2011/06/08/auto-ignore-non-existing-properties-with-automapper/



1
Ini tidak berfungsi saat menyuntikkan IMapper. Mapper.GetAllTypeMaps tidak ada di versi terbaru dari AutoMapper. Selain itu, ketika saya mengatur peta saya di AutoMapper.Profile dan kemudian menyuntikkan IMapper, saya mendapatkan pengecualian ini "Mapper tidak diinisialisasi. Panggil Inisialisasi dengan konfigurasi yang sesuai. Jika Anda mencoba menggunakan instance mapper melalui wadah atau yang lain, pastikan Anda tidak memiliki panggilan ke metode Mapper.Map statis, dan jika Anda menggunakan metode ekstensi ProjectTo atau UseAsDataSource, pastikan Anda mengirimkan contoh IConfigurationProvider yang sesuai. "
Ristogod

Saya baru saja 'Mapper' does not contain a definition for 'GetAllTypeMaps' [DSSTools]..
Bassie

2
@Bassie Gunakan Mapper.Configuration.GetAllTypeMaps() sumber
Mike Bovenlander

28

Sekarang ada (AutoMapper 2.0) IgnoreMapatribut, yang akan saya gunakan daripada sintaks yang lancar yang merupakan IMHO agak berat.


35
Atribut abaikan kebocoran auto-mapper melalui aplikasi Anda.
Phill

11
AutoMapper adalah satu hal yang saya tidak keberatan bocor di semua tempat. ;)
Pawel Krakowiak

4
Anda selalu dapat mempertimbangkan untuk diturunkan IgnoreMapAttribute.
Alapago

1
Ini adalah cara yang baik untuk mengabaikan properti dasar yang diwarisi di banyak objek. Menghemat dari keharusan untuk mengabaikannya di setiap konfigurasi pemetaan.
Chase Florell

23

Saat memetakan model tampilan kembali ke model domain, mungkin jauh lebih bersih untuk hanya memvalidasi daftar anggota sumber daripada daftar anggota tujuan

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

Sekarang validasi pemetaan saya tidak gagal, membutuhkan yang lain Ignore(), setiap kali saya menambahkan properti ke kelas domain saya.


7
INI adalah apa yang saya cari, sangat berguna ketika hanya memodifikasi subset dari properti objek domain dari DTO yang jauh lebih sederhana.
Adam Tolley

5
Ini adalah jawaban anak-anak, buat yang resmi jadi pemula tidak akan bingung
Piotr M

0

Bisa menggunakan IgnoreAttribute di properti yang perlu diabaikan


2
Ini [IgnoreMap]dariIgnoreMapAttribute
fiorebat

-5

Halo Semua Silakan Gunakan ini berfungsi dengan baik ... untuk auto mapper gunakan beberapa .ForMember dalam 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;
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.