Questo è lungo.Automapper che crea una nuova istanza anziché le proprietà della mappa
Quindi, ho un modello e un viewmodel che sto aggiornando da una richiesta AJAX. controller Web API riceve il ViewModel, che ho poi aggiornare il modello esistente utilizzando automapper come di seguito:
private User updateUser(UserViewModel entityVm)
{
User existingEntity = db.Users.Find(entityVm.Id);
db.Entry(existingEntity).Collection(x => x.UserPreferences).Load();
Mapper.Map<UserViewModel, User>(entityVm, existingEntity);
db.Entry(existingEntity).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch
{
throw new DbUpdateException();
}
return existingEntity;
}
ho automapper configurato in questo modo per l'utente -> UserViewModel (e ritorno) mappatura.
Mapper.CreateMap<User, UserViewModel>().ReverseMap();
(Si noti che l'impostazione in modo esplicito la mappa opposto e omettendo il ReverseMap presenta lo stesso comportamento)
Sto avendo un problema con un membro del Modello/ViewModel che è un ICollection di un oggetto diverso :
[DataContract]
public class UserViewModel
{
...
[DataMember]
public virtual ICollection<UserPreferenceViewModel> UserPreferences { get; set; }
}
Il modello corrispondente è come tale:
public class User
{
...
public virtual ICollection<UserPreference> UserPreferences { get; set; }
}
Il problema:
Ogni proprietà dell'Utente e classi UserViewModel mappe correttamente, fatta eccezione per la ICollections
di PreferenzeUtente/UserPreferenceViewModels mostrato sopra. Quando queste raccolte vengono mappate da ViewModel al modello, anziché dalle proprietà della mappa, viene creata una nuova istanza di un oggetto UserPreference dal ViewModel, anziché aggiornare l'oggetto esistente con le proprietà ViewModel.
Modello:
public class UserPreference
{
[Key]
public int Id { get; set; }
public DateTime DateCreated { get; set; }
[ForeignKey("CreatedBy")]
public int? CreatedBy_Id { get; set; }
public User CreatedBy { get; set; }
[ForeignKey("User")]
public int User_Id { get; set; }
public User User { get; set; }
[MaxLength(50)]
public string Key { get; set; }
public string Value { get; set; }
}
e il corrispondente ViewModel
public class UserPreferenceViewModel
{
[DataMember]
public int Id { get; set; }
[DataMember]
[MaxLength(50)]
public string Key { get; set; }
[DataMember]
public string Value { get; set; }
}
e la configurazione automapper:
Mapper.CreateMap<UserPreference, UserPreferenceViewModel>().ReverseMap();
//also tried explicitly stating map with ignore attributes like so(to no avail):
Mapper.CreateMap<UserPreferenceViewModel, UserPreference>().ForMember(dest => dest.DateCreated, opts => opts.Ignore());
Quando la mappatura un'entità UserViewModel a un utente, ICollection di UserPreferenceViewModels è anche mappato l'ICollection dell'utente di UserPreferences, come dovrebbe.
Tuttavia, quando ciò si verifica, le singole proprietà dell'oggetto UserPreference come "DateCreated", "CreatedBy_Id" e "User_Id" vengono annullate come se venisse creato un nuovo oggetto anziché le singole proprietà copiate.
Questo è ulteriormente dimostrato come quando si associa un UserViewModel che ha solo 1 oggetto UserPreference nella raccolta, quando si ispeziona DbContext, ci sono due oggetti UserPreference locali dopo l'istruzione della mappa. Uno che sembra essere un nuovo oggetto creato da ViewModel e uno che è l'originale dal modello esistente.
Come faccio a rendere automapper l'aggiornamento di una collezione di un modello esistente; i membri di s, invece di istanziare nuovi membri dalla raccolta di ViewModel? Cosa sto facendo di sbagliato qui?
Screenshots per dimostrare prima/dopo Mapper.Mappa()
Potrebbe essere necessario eseguire l'override del 'GetHashCode' in' 'UserPreference' e UserPreferenceViewModel' in modo che la raccolta li può identificare come la stessa. Forse l'automapper ha un po 'di magia, ma io sono dubbioso – HaroldHues
Yup, deve aver copiato/incollato la linea sbagliata per la linea CreateMap. Sto esaminando l'override del GetHashCode attualmente, ti riporto se viene trovato qualcosa. Grazie per l'aiuto. –
È necessario fare un passo indietro e interrompere l'uso di AutoMapper per mappare da ViewModel ai modelli di entità o di dominio. AutoMapper non è stato creato per questo e non funzionerà come previsto. Usa AutoMapper ** SOLO ** per mappare da Entity/Domain Model a ViewModel/DTO/BindingModel, ** NEVER ** other way around. Ciò è fortemente scoraggiato dall'autore di AutoMapper – Tseng