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?

Msam85
sumber
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 .

smartcaveman
sumber
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.

Steve Rukuts
sumber
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());
Richard
sumber
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
FYI: digabung dari stackoverflow.com/questions/4052579/…
Shog9
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/

Stéphane
sumber
3
FYI: digabung dari stackoverflow.com/questions/4052579/…
Shog9
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.

Guillaume
sumber
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.

Loren Paulsen
sumber
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

Naresh
sumber
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;
ravikant sonare
sumber