0

I want to update complex object property in my asp.net core 2 project.

My UserProjects class looks like:

    public class UserProject
    {
        public int UserId { get; set; }
        public User User { get; set; }
        public int ProjectId { get; set; }
        public Project Project { get; set; }
    }

My method which I want to change project status from ready to pending. With simple objects I know but with complex objects I can not achieve parameter like entry.ProjectStatus even I will use my _context.Projects. My method looks like:

        [HttpPost("changeprojectstatus/{userId}/{projectId}")]
        public IActionResult ChangeProjectStatus(int userId, int projectId)
        {
            var result = _context.UserProjects.Where(x => x.UserId == userId && x.ProjectId == 
                                                                          projectId);

            if (result != null)
            {
                // Make changes on entity
                var pr = result.Where(x => x.Project.Status == ProjectStatus.Ready);

                // Update entity in DbSet
                _context.Projects.Update(pr);
                _context.SaveChanges();
            }


            if (userId != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
                return Unauthorized();

            return Ok();
        }
Arzu Suleymanov
  • 671
  • 2
  • 11
  • 33
  • So what is wrong with your method? Can you provide more specific information, what exception you are getting and where? – Fabio Dec 18 '19 at 09:46
  • You mean update containment objects of your class? If so, you need to use the `UserProject.Project = new Project()...` this is the recommended way. – panoskarajohn Dec 18 '19 at 09:49
  • In my code I am finding project status which is ready I would like to change it to pending and this part is missing in my code. And in this code it throws exception can not convert UserProjects to Project – Arzu Suleymanov Dec 18 '19 at 09:50
  • @panoskarajohn could you be more precise if possible with code – Arzu Suleymanov Dec 18 '19 at 09:50
  • Ok I see your error that you said. Add to your `result` query this `_context.UserProjects.Where(x => x.UserId == userId && x.ProjectId == projectId).Select(up => up.Project)` – panoskarajohn Dec 18 '19 at 09:53
  • Well in my previous comment i meant sth else. When creating a new UserProject. For the property `Project` use `new Project()` which is sth different from what you ask. This is out of the scope of this question. – panoskarajohn Dec 18 '19 at 09:58
  • In this case I select Project , ok, `var pr = result.Where(x => x.Status == ProjectStatus.Ready)` still selecting status but how I can change it? pr.PrjectStatus still not appearing. And in my code I am still getting same which I mentioned above, but I am not still able to change status. – Arzu Suleymanov Dec 18 '19 at 10:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/204476/discussion-between-panoskarajohn-and-arzu-suleymanov). – panoskarajohn Dec 18 '19 at 10:07

3 Answers3

1

Your error is here you are trying to update Projects using a UserProject class. In your result query you get back UserObject.

At your update you update the Projects object, which is different than your UserProjects.

I see two solutions, choose based on what you need.

First update the Projects object:

[HttpPost("changeprojectstatus/{userId}/{projectId}")]
        public IActionResult ChangeProjectStatus(int userId, int projectId)
        {
            var result = _context.UserProjects.First(x => x.UserId == userId && x.ProjectId == 
                                                                          projectId).Select(up => up.Project);

            if (result != null)
            {
                // Make changes on entity
                var pr = result.FirstOrDefault(x => x.Status == ProjectStatus.Ready);
                pr.Status = ProjectStatus.Pending; //update
                // Update entity in DbSet
                _context.Projects.Update(pr);
                _context.SaveChanges();
            }


            if (userId != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
                return Unauthorized();

            return Ok();
        }

Second update the UserProjects object

[HttpPost("changeprojectstatus/{userId}/{projectId}")]
        public IActionResult ChangeProjectStatus(int userId, int projectId)
        {
            var result = _context.UserProjects.First(x => x.UserId == userId && x.ProjectId == 
                                                                          projectId);

            if (result != null)
            {
                // Make changes on entity
                var pr = result.FirstOrDefault(x => x.Project.Status == ProjectStatus.Ready);
                pr.Peoject.Status = ProjectStatus.Pending; //update the status
                // Update entity in DbSet
                _context.UserProjects.Update(pr);
                _context.SaveChanges();
            }


            if (userId != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
                return Unauthorized();

            return Ok();
        }
panoskarajohn
  • 1,846
  • 1
  • 21
  • 37
  • :) posted same time as me – davethecoder Dec 18 '19 at 10:09
  • That is ok. He/She is stuck at the update with EF core. Not only at the different types error. You should update your answer. Also feel free to edit mine. – panoskarajohn Dec 18 '19 at 10:11
  • `Object reference not set to an instance of an object.` I got this error – Arzu Suleymanov Dec 18 '19 at 10:14
  • That means that you yielded no result meaning `null`. This is why you got this error. You should check for null and do not update if so. This is because of `FirstOrDefault`. If you have `First` the code will throw an exception -> https://stackoverflow.com/questions/1024559/when-to-use-first-and-when-to-use-firstordefault-with-linq – panoskarajohn Dec 18 '19 at 10:15
  • @panoskarajohn I cahnged to FirstOrDefault this time no compiler error but `Object reference not set to an instance of an object` – Arzu Suleymanov Dec 18 '19 at 10:22
  • This means you got a `null` in your code. This can be coming from the DB. This is where we cannot help you. Since this can mean various things.Try debugging and add null checks, or check your data.. Please take a look here as well -> https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it – panoskarajohn Dec 18 '19 at 10:25
1

few issues:

  1. You are starting with a collection of UserProjects and not Projects
  2. in your pr variable You are still creating a collection of UserProjects, because you are running a where, and not a firstOrDefault
  3. You are trying to send a list of UserProjects as a single type of Project

First make sure PR is single, not collection. Then if UserProjects is the same as Projects you can use AutoMapper to map your USerProject to a type of Project and then update.

The big clue here was in the error message that one type cannot be another.

davethecoder
  • 3,856
  • 4
  • 35
  • 66
0

Changed my code to Projects and it works fine now: Code looks like:

[HttpPost("changeprojectstatus/{userId}/{projectId}")]
public IActionResult ChangeProjectStatus(int userId, int projectId)
{
    var project = _context.Projects.Where(x => x.Id == projectId);

    {
        // Make changes on entity
        var pr = project.FirstOrDefault(x => x.Status == ProjectStatus.Ready);
        pr.Status = ProjectStatus.Pending; //update the status
        // Update entity in DbSet
        _context.Projects.Update(pr);
        _context.SaveChanges();
    }

    if (userId != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
        return Unauthorized();

    return Ok();
}
Arzu Suleymanov
  • 671
  • 2
  • 11
  • 33