I am trying to use Entity Framework and have Automapper update my entity from my contract.
My code looks like this:
var temp = OrderContract;
Order order = dataAccess.FindOne<Order>(x => x.OrderId == temp.OrderId)
?? new Order();
Mapper.Map(OrderContract, order);
if (order.OrderId <= 0)
dataAccess.Add(order);
(Note: I am using the Repository Pattern. dataAccess.FindOne calls CreateQuery to return one entity.)
The problem I am having is with the relationships. I get this error when I do an update (inserts work just fine):
The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
I am guessing that automapper is not updating the way I want it to. From the error message and googling around I have surmised that my relationships that are collections (and maybe even the ones that are not collections) are being recreated by Automapper.
How can I tell Automapper to just update and not remake any objects or collections?
Guesses:
I read that maybe I need to use the UseDestinationValue option for automapper. I went back and put that on all my collections But when I do that then my inserts fail with a foreign key violation.
Code Mappings:
Using UseDestinationValue only on one collection (this one inserts but will not update):
//+ Source
Mapper.CreateMap<SourceContract, Source>()
.IgnoreAllNonExisting();
//+ SelectedRequirement
Mapper.CreateMap<SelectedRequirementContract, SelectedRequirement>()
.ForMember(x => x.SelectedRequirementId, opt => opt.MapFrom(src => src.RequirementId))
.IgnoreAllNonExisting();
//+ Comment Contract
Mapper.CreateMap<CommentContract, Comment>()
.ForMember(x => x.CommentText, opt => opt.MapFrom(src => src.Comment))
.IgnoreAllNonExisting();
//+ Order Automapper setup
Mapper.CreateMap<OrderContract, Order>()
.ForMember(x => x.Source, opt => opt.MapFrom(src => src.Source))
.ForMember(x => x.Comment, opt => opt.MapFrom(src => src.Comment))
//Although a mapping was created for Comment entity,
//we still need to map the CommentId of the Order entity otherwise it will remain null during an update.
//Another way to handle this would be to Delete CommentId from the Order entity.
//However, if anyone updates (Update from model) OrderDataModel.edmx that property would show up again thus causing
//a null value to be inserted during an update.
.ForMember(x => x.CommentId, opt => opt.MapFrom(src => src.Comment.CommentId))
.ForMember(x => x.SelectedRequirements, opt => {opt.UseDestinationValue(); opt.MapFrom(src => src.Requirements);})
.ForMember(x => x.OrderStateId, opt => opt.MapFrom(src => src.StateId))
.ForMember(x => x.OrderStateId, opt => opt.MapFrom(src => src.StateId))
.IgnoreAllNonExisting();
Using UseDestinationValue everywhere (this one does not insert):
//+ Source
Mapper.CreateMap<SourceContract, Source>()
.IgnoreAllNonExisting();
//+ SelectedRequirement
Mapper.CreateMap<SelectedRequirementContract, SelectedRequirement>()
.ForMember(x => x.SelectedRequirementId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.RequirementId); })
.IgnoreAllNonExisting();
//+ Comment Contract
Mapper.CreateMap<CommentContract, Comment>()
.ForMember(x => x.CommentText, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Comment); })
.IgnoreAllNonExisting();
//+ Order Automapper setup
Mapper.CreateMap<OrderContract, Order>()
.ForMember(x => x.Source, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Source); })
.ForMember(x => x.Comment, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Comment); })
//Although a mapping was created for Comment entity,
//we still need to map the CommentId of the Order entity otherwise it will remain null during an update.
//Another way to handle this would be to Delete CommentId from the Order entity.
//However, if anyone updates (Update from model) OrderDataModel.edmx that property would show up again thus causing
//a null value to be inserted during an update.
.ForMember(x => x.CommentId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Comment.CommentId); })
.ForMember(x => x.SelectedRequirements, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.Requirements); })
.ForMember(x => x.OrderStateId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.StateId); })
.ForMember(x => x.OrderStateId, opt => { opt.UseDestinationValue(); opt.MapFrom(src => src.StateId); })
.IgnoreAllNonExisting();
What do I need to so I can insert and update?
OrderandOrderContractclasses? - shuniarMapper.Map(sourceObject, destObject)- Vaccano