1

I have a problem where Entity Framework (Core) is deleting an object upon update. I think this is related to Automapper (map DTO Resource to object). I have other objects mapped the exact same way as this object and updates work just fine.

public async Task<IActionResult> UpdateFeedback(Guid Id, [FromBody] FeedbackResource feedbackResource)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);
    //removing or else get a tracking error with EF
    feedbackResource.FeedbackType = null;
    var feedback = await feedbackRepository.GetFeedback(Id);

    if (feedback == null)
        return NotFound();

    //if I use this line to map, EF will delete the object upon save.  

    mapper.Map<FeedbackResource, Feedback>(feedbackResource, feedback);

    // if I map manually, i get no error
    //feedback.Title = feedbackResource.Title;
    //feedback.Details = feedbackResource.Details;
    //feedback.IsGoodFeedback = feedbackResource.IsGoodFeedback;
    //feedback.IsReviewed = feedbackResource.IsReviewed;
    //feedback.FeedbackTypeId = feedbackResource.FeedbackTypeId;

    //if(feedbackResource.IsReviewed){
    //    feedback.ReviewDate = DateTime.Now;
    //    feedback.ReviewedBy = UserId;
    //} else {
    //    feedback.ReviewDate = null;
    //    feedback.ReviewedBy = null;
    //}

    await uow.CompleteAsync();

    return Accepted(feedback); 
}

I have no idea what to troubleshoot here and cannot see this issue on any google search.

SpruceMoose
  • 9,737
  • 4
  • 39
  • 53
a2ron44
  • 1,711
  • 1
  • 13
  • 18
  • 2
    You should start by adding a breakpoint to your code so that you can examine the result of the mapping operation and to ensure that all the properties of the FeedbackResource are bound and present as expected. – Mike Brind Dec 06 '17 at 09:40
  • Impossible to answer this w/o a [mre]. – Gert Arnold May 31 '23 at 10:46
  • For me, this issue ended up being caused by an interaction between the automapper and EntityFramework. This was described well by https://stackoverflow.com/questions/32120042/automapper-creating-new-instance-rather-than-map-properties – Ben W Jun 18 '21 at 00:15

4 Answers4

4

I was faced with a similar situation (ef core 1.1). I will assume that your problem is similar to mine.

Also a similar problem is described here

I have the following models:

1) ApplicatonUser - standard user from EF

2) AnyDAL - any class in DB, which have link to user

 public class AnyDAL
 {
    public long Id { get; set; }

    public long UserId { get; set; }
    public ApplicationUser User { get; set; }
}

3) AnyDTO - model that comes from the browser side. Like your's [FromBody] FeedbackResource feedbackResource

public class AnyDTO
{
    public long Id { get; set; }

    public long UserId { get; set; }

    /// It is root of all evil. See below.
    /// And yes, it is bad practice.
    public ApplicationUser User { get; set; }
}

Scenario:

1) get AnyDAL from the database;

2) map AnyDTO on AnyDAL using AutoMapper _mapper.Map(DTO, DAL);

3) SaveChanges()

In one case, SaveChanges() leads to Delete, in other to Update.

What we should know: in my case property AnyDTO.User is always null after deserialization.

The choice between delete and update depends on the value of property AnyDAL.User before mapping:

1)AnyDAL.User is null - we get Update.

2)AnyDAL.User is NOT null - we get Delete.

In other words. If property AnyDAL.User changed from some value to null - entity will be deleted. Despite the fact that AnyDAL.UserId remains the same.

There is two ways to solve it:

1) Remove property User from AnyDTO;

2) Property AnyDTO.User should always has value.

0

This is a little old but I ran into the same issue with EF Core 2.2 and based on this EntityFrameworkCore it is still an issue in 3.0

The issue seems to be that the navigation property being null is causing the entity to be deleted.

I was able to resolve by configuring lazy loading

Install this package

Microsoft.EntityFrameworkCore.Proxies

Enable lazy loading in the configuration

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseLazyLoadingProxies();
Dilip Hirapara
  • 14,810
  • 3
  • 27
  • 49
0

for me, this was resolved if I marked as Detached the entity, use automapper to map, then mark entity as Modified.

        _context.Entry(product).State = EntityState.Detached;

        _mapper.Map<ProductVM, Product>(viewModelProduct, product);

        _context.Entry(product).State = EntityState.Modified;

        _context.SaveChanges();
Boies Ioan
  • 892
  • 8
  • 12
-1

Entity framework needs to know if you want to update or delete. You need to solve this by giving the EntityState before SaveChanges():

dbContext.Entry(yourUpdatingEntity).State = EntityState.Modified;
dbcontect.SaveChages();
Sadjad Khazaie
  • 2,102
  • 22
  • 22