EF6 AutoMapper6 Perilaku orang tua/anak berbeda

Saya baru saja memperbarui seluruh aplikasi WCF dari EF4/AutoMapper 1.1 ke EF6/AutoMapper 6.0.0.2 dan perilakunya tidak sepenuhnya sama.

Ini tidak berhasil untuk saya: Kerangka Kerja Entitas - Tambahkan Entitas Anak

Sebelum :

child.Parent = parentObject

OR

parentObject.Children.Add(child)

memiliki hasil yang sama secara real time (saat debugging == sebelum SaveChanges), jadi saya memutuskan untuk menggunakan child.Parent = parentObject agar mudah dibaca. child.Parent = parentObject menambahkan anak di parentObject secara otomatis. Anak itu juga ditambahkan ke db.

Sekarang : child.Parent = parentObject tidak cukup lagi (anak tidak ditambahkan di db), saya harus menambahkan parentObject.Children.Add(child). Terkadang saya membutuhkan link child.Parent = parentObject, jadi saya harus menulis kedua baris tersebut. Dapatkah seseorang menjelaskan kepada saya mengapa itu tidak berfungsi lagi?

Juga : Saya bisa menulis sebelum :

Mapper.CreateMap< Patient, PATIENTENTITY >()
                .ForMember(dest => dest.Gender, opt => opt.ResolveUsing< PatientGenderResolver >())
                .ForMember(dest => dest.REF_GENDER, opt => opt.Ignore())

di mana dest.Gender adalah PK(int) dan PatientGenderResolver temukan id(int) Gender di tabel REF_GENDER. Pemetaan ini cukup untuk menyetel PATIENTENTITY.REF_GENDER secara real-time berkat penyelesai Id.

Sekarang id telah disetel tetapi PATIENTENTITY.REF_GENDER tetap nol. Saya juga mencoba mengatur langsung PATIENTENTITY.REF_GENDER dengan penyelesai tetapi menambahkan Gender di tabel REF_GENDER...

Jadi sekali lagi, bisakah seseorang menjelaskan kepada saya mengapa itu tidak berfungsi lagi?

EDIT Beberapa presisi : Sebelum :

    patientEntity = Mapper.PatientToEntity(patientModel);
    //patientEntity.REF_GENDER is null
    Context.PATIENTENTITIES.AddObject(patientEntity);
    //patientEntity.REF_GENDER is set !
    Context.SaveChanges();

Sekarang :

patientEntity = Mapper.PatientToEntity(patientModel);
//patientEntity.REF_GENDER is null
Context.PATIENTS.Add(patientEntity);
//patientEntity.REF_GENDER is still null !
//patientEntity.REF_GENDER = Context.REF_GENDER.Find(patientEntity.Gender);//I am obliged to add this line everywhere for every REF !
Context.SaveChanges();

Dugaan saya adalah kedua masalah yang saya alami saling berkaitan

EDIT Saya baru saja kembali mengerjakan proyek saya. Saya sekarang memiliki EF6 dan Automapper 1.1. Masalahnya sama persis jadi saya kira Automapper tidak terlibat.

EDIT Saya mengatasi masalah REF_GENDER

patientEntity = Mapper.PatientToEntity(patientModel, Context);
public PATIENT PatientToEntity(Patient patient, EntityContainer context)
{
    PATIENT entity = AutoMapper.Mapper.Map<Patient, PATIENT>(patient);
    if (patient.Id == null || patient.Id == Guid.Empty)
        entity.PatientId = Guid.NewGuid();
    else
        entity.PatientId = patient.Id;

    entity.REF_GENDER = context.REF_GENDER.Find(entity.Gender);

    return entity;
}

Tampaknya, konteksnya harus sama jika tidak, REF_GENDER baru akan ditambahkan ke db


person Flou    schedule 10.10.2018    source sumber


Jawaban (1)


Anda tidak menyebutkannya secara eksplisit, tetapi Anda tidak hanya berpindah dari EF 4 ke 6, tetapi juga dari ObjectContext ke DbContext. Itu adalah perbedaan yang luar biasa dalam perilaku kelas entitas.

Dalam ObjectContext API kelas entitas yang dihasilkan diisi dengan kode yang bekerja sama erat dengan konteks di mana mereka terlibat. Properti referensi seperti child.Parent akan terlihat seperti:

public Parent Parent
{
    get
    {
        return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Parent>("model.FK_Child_Parent", "Parent").Value;
    }
    set
    {
        ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Parent>("model.FK_Child_Parent", "Parent").Value = value;
    }
}

Jadi pengaturan properti ini adalah pengaturan properti Value dari EntityReference<Parent>. Kode EF4.1 tidak bersifat publik, jadi kami hanya bisa menebak apa yang terjadi di dalamnya. Satu hal yang jelas: ini mengubah status childs menjadi Added -- jika child belum melekat pada konteksnya.

Untungnya EF meninggalkan penguncian vendor yang kaku ini ketika merilis DbContext API (tidak kurang di EF 4.1). Sekarang properti yang dihasilkan ini tidak lain hanyalah properti otomatis:

public Parent Parent { get; set; }

Hal ini mempermudah penyatuan mode kerja database-first dan code-first dengan EF. Faktanya, kelas entitas yang mengutamakan kode dan yang mengutamakan basis data kini menjadi POCO.

Harganya (jika Anda mau) adalah EF tidak bisa melacak segala sesuatu yang terjadi sedekat mungkin sebelumnya. Sebelumnya, semua kelas entitas yang diwarisi dari EntityObject, dan EF dapat melacak semua interaksinya. Pernyataan...

child.Parent = parentObject;

akan menarik child yang belum diketahui ke dalam konteks melalui parentObject terlampir.

Sekarang, ketika seseorang menetapkan child.Parent, tidak seorang pun kecuali child yang mengetahui apa yang terjadi, bahkan Parent. Artinya: tidak ada cara apa pun bagi EF untuk menyadari perubahan ini ketika pelacak perubahannya mengeksekusi DetectChanges (seperti yang sering terjadi).

Itu sebabnya menggunakan DbContext Anda harus menambahkan sendiri anak baru ke konteksnya, baik dengan mengatur statusnya secara eksplisit, atau menambahkannya ke context.Children. Atau dengan menambahkannya ke parent.Children, yang merupakan perubahan yang dapat dideteksi oleh pelacak perubahan, jika parent terpasang.

person Gert Arnold    schedule 13.10.2018
comment
Anda benar @Gert Arnold, berpindah dari ObjectContext ke DbContext adalah perbedaan besar dalam perilaku kelas entitas. Terima kasih atas jawaban dan format Anda. Akhirnya saya menambahkan child.Parent = parentObject DAN parentObject.Children.Add(child) agar kode saya berfungsi kembali. Dan saya mengatur referensi di mapper seperti yang saya tulis. - person Flou; 16.10.2018
comment
Saya baru saja menyelesaikan migrasi setelah satu minggu. Saya sedang menguji peningkatan kinerja dan dalam setiap kasus ini lebih buruk daripada ef4 tidak seperti docs.microsoft.com/fr-fr/ef/ef6/fundamentals/kinerja/ berkata... Saya cukup kecewa :( - person Flou; 17.10.2018
comment
Ya, itu tidak terduga. Anda dapat mencoba mengajukan pertanyaan tentang kasus tertentu. Mungkin, mengingat hal di atas, ada beberapa hal yang harus Anda lakukan secara berbeda di EF6 dibandingkan dengan EF4, misalnya menggunakan asosiasi kunci asing bukannya asosiasi independen. - person Gert Arnold; 17.10.2018
comment
1 - Saya rasa saya sudah menggunakan FK daripada asosiasi independen tapi saya tidak yakin. Maksudku, aku sudah punya satu FK public int PrincipalEntity_Id { get; mengatur; } (tanpa [ForeignKey(PrincipalEntity_Id)]) DAN satu properti navigasi public Principal PrincipalEntity { get; mengatur; } tapi saya tidak menggunakan [ForeignKey(PrincipalEntity_Id)] karena ini adalah kode yang dibuat secara otomatis dan menurut saya itu cukup baik untuk dipahami oleh EF6 - person Flou; 19.10.2018
comment
2 - Saya sedang menyelidiki untuk meningkatkan kinerja pemuatan. Saya baru memperhatikan dengan SQL Profiler bahwa kueri Where menggunakan pemuatan lambat : hanya satu pilihan/di mana untuk objek tertinggi. Kemudian saya perhatikan bahwa AutoMapper membuat banyak pilihan/di mana saat memetakan karena pemuatan yang lambat. Tampaknya tidak terlalu efektif! Jadi saya mencoba metode .Sertakan (banyak) dalam kueri utama: ini adalah kueri multi-gabung yang tampaknya lebih efektif bagi saya. Namun pemetaannya masih melakukan jumlah pilih/di mana yang sama, jadi saya ingin tahu apakah AutoMapper masih dapat dibenarkan? - person Flou; 19.10.2018
comment
Saya sarankan Anda mengajukan pertanyaan baru dengan rincian yang cukup untuk menjawabnya. Saya tidak bisa menjawab ini dari info di komentar Anda dan itu juga di luar cakupan pertanyaan ini. - person Gert Arnold; 19.10.2018
comment
3 - Saya juga lupa... performanya tidak jelek, saya hanya lupa eksekusi dingin dan hangat, pada akhirnya hasilnya sama saja - person Flou; 19.10.2018