У меня есть Supplier.cs
Entity и его ViewModel SupplierVm.cs
. Я пытаюсь обновить существующий Поставщик, но я получаю Желтый Экран Смерти (YSOD) с сообщением об ошибке:
Операция завершилась неудачно: отношение не может быть изменено, поскольку одно или несколько свойств внешнего ключа не имеют значения NULL. Когда происходит изменение отношения, соответствующее свойство внешнего ключа устанавливается равным нулевому значению. Если внешний ключ не поддерживает нулевые значения, необходимо определить новое отношение, для свойства внешнего ключа должно быть назначено другое ненулевое значение, или не связанный с ним объект должен быть удален.
Я думаю Я знаю, почему это происходит, но я не уверен, как его исправить.. Здесь screencast того, что происходит. Я думаю, причина, по которой я получаю ошибку, состоит в том, что эти отношения теряются, когда AutoMapper делает свою работу.
CODE
Вот Сущности, которые, по моему мнению, актуальны:
public abstract class Business : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public string TaxNumber { get; set; }
public string Description { get; set; }
public string Phone { get; set; }
public string Website { get; set; }
public string Email { get; set; }
public bool IsDeleted { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
public virtual ICollection<Address> Addresses { get; set; } = new List<Address>();
public virtual ICollection<Contact> Contacts { get; set; } = new List<Contact>();
}
public class Supplier : Business
{
public virtual ICollection<PurchaseOrder> PurchaseOrders { get; set; }
}
public class Address : IEntity
{
public Address()
{
CreatedOn = DateTime.UtcNow;
}
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string Area { get; set; }
public string City { get; set; }
public string County { get; set; }
public string PostCode { get; set; }
public string Country { get; set; }
public bool IsDeleted { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
public int BusinessId { get; set; }
public virtual Business Business { get; set; }
}
public class Contact : IEntity
{
public Contact()
{
CreatedOn = DateTime.UtcNow;
}
public int Id { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string Department { get; set; }
public bool IsDeleted { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
public int BusinessId { get; set; }
public virtual Business Business { get; set; }
}
И вот мой ViewModel:
public class SupplierVm
{
public SupplierVm()
{
Addresses = new List<AddressVm>();
Contacts = new List<ContactVm>();
PurchaseOrders = new List<PurchaseOrderVm>();
}
public int Id { get; set; }
[Required]
[Display(Name = "Company Name")]
public string Name { get; set; }
[Display(Name = "Tax Number")]
public string TaxNumber { get; set; }
public string Description { get; set; }
public string Phone { get; set; }
public string Website { get; set; }
public string Email { get; set; }
[Display(Name = "Status")]
public bool IsDeleted { get; set; }
public IList<AddressVm> Addresses { get; set; }
public IList<ContactVm> Contacts { get; set; }
public IList<PurchaseOrderVm> PurchaseOrders { get; set; }
public string ButtonText => Id != 0 ? "Update Supplier" : "Add Supplier";
}
Конфигурация отображения AutoMapper My выглядит следующим образом:
cfg.CreateMap<Supplier, SupplierVm>();
cfg.CreateMap<SupplierVm, Supplier>()
.ForMember(d => d.Addresses, o => o.UseDestinationValue())
.ForMember(d => d.Contacts, o => o.UseDestinationValue());
cfg.CreateMap<Contact, ContactVm>();
cfg.CreateMap<ContactVm, Contact>()
.Ignore(c => c.Business)
.Ignore(c => c.CreatedOn);
cfg.CreateMap<Address, AddressVm>();
cfg.CreateMap<AddressVm, Address>()
.Ignore(a => a.Business)
.Ignore(a => a.CreatedOn);
Наконец, здесь мой метод SupplierController:
[HttpPost]
public ActionResult Edit(SupplierVm supplier)
{
if (!ModelState.IsValid) return View(supplier);
_supplierService.UpdateSupplier(supplier);
return RedirectToAction("Index");
}
И здесь метод UpdateSupplier
на SupplierService.cs
:
public void UpdateSupplier(SupplierVm supplier)
{
var updatedSupplier = _supplierRepository.Find(supplier.Id);
Mapper.Map(supplier, updatedSupplier); // I lose navigational property here
_supplierRepository.Update(updatedSupplier);
_supplierRepository.Save();
}
Я сделал нагрузку на чтение и, согласно это сообщение в блоге, то, что я должен работать! Я также читал такие вещи, как это, но я думал, что я проверил бы с читателями, прежде чем переключать AutoMapper для обновления сущностей.