locked
Entity Framework update the parents and add the child objects. Getting error RRS feed

  • Question

  • User-1637592233 posted

    During the Edit I have to update some of the tables with the value from the form, and also have to add some new records on the table.

    I am always getting the same error:

    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.

    My view model is as below:

    public class CorporateCustomerUpdateViewModel
    {
        public Guid Id { get; set; }
        public string FullName { get; set; }
        public CorporateCustomerViewModel CorporateCustomer { get; set; }
    }
    
    public class CorporateCustomerViewModel 
    {
        public int BusinessTypeId { get; set; }
        public List<CorporateMemberViewModel> CorporateMembers { get; set; }
    }
    
    public class CorporateMemberViewModel
    {
        public string IdNumber { get; set; }
        public string Name { get; set; }
        public string Document { get; set; }
    } 

    Entities::

    public class User
    {   
        public Guid Id { get; set; }
        public string FullName { get; set; }
        public virtual CorporateCustomer CorporateCustomer { get; set; }
    }
    
    public class CorporateCustomer
    {  
        public int BusinessTypeId { get; set; }
        public virtual ICollection<CorporateMember> CorporateMembers { get; set;}
    }
    
    public class CorporateMember
    {
        public string IdNumber { get; set; }
        public string Name { get; set; }
        public string Document { get; set; }
    }

    I am using AutoMapper to map the fields from view models to entities.

    Configuration looks like:

    public class CorporateCustomerMapper : Profile
    {
       CreateMap<CorporateCustomerUpdateViewModel, User>();
    }

    I am trying to Update the User table as below:

    public void UpdateCorporateCustomerDetail(CorporateCustomerUpdateViewModel model)
    {
        var userRepo = _genericUnitOfWork.GetRepository<User, Guid>();
    
        var user = userRepo.GetById(model.Id); 
        var entity = _mapper.Map(model, user); 
        //mapping CorporateCustomerUpdateViewModel to User
    
         userRepo.Update(entity);
        _genericUnitOfWork.SaveChanges();
    }

    GetById

    public TEntity GetById(TKey id)
    {
        return _dbSet.Find(id);
    }

    After the MAP the user.CorporateCustomer.CorporateMembers is getting null because there is no value on model.CorporateCustomer.CorporateMembers.

    But that should not be getting null because there are already some CorporateMembers in the database which I get during GetById.

    I think here is the problem because EF is going to update the null entry.

    Here in the link provided is the discussion about the same scenarios.

    https://stackoverflow.com/questions/5538974/the-relationship-could-not-be-changed-because-one-or-more-of-the-foreign-key-pro

    https://stackoverflow.com/questions/5538974/the-relationship-could-not-be-changed-because-one-or-more-of-the-foreign-key-pro

    I have gone through both the links. But there are the discussion with one ChildObjects and no AutoMapper. I cannot figure out where did I actually did something wrong, and where I should change my code.

    Please can you suggest some code changes, or some hints?

    Sunday, March 4, 2018 3:36 AM

All replies

  • User1120430333 posted

    Myself, I avoid the UoW and the generic repository patterns like the plague. 

    https://www.infoworld.com/article/3117713/application-development/design-patterns-that-i-often-avoid-repository-pattern.html

    I would rather use the non-generic repository with Data Access Layer using the DAO pattern.

    Or just Data Access Layer using the Data Access Object pattern.

    Sunday, March 4, 2018 5:24 AM
  • User-1637592233 posted

    Thanks for sharing the link and suggesting a solution but 

    Is that approach going to help me for the current problems?

    Sunday, March 4, 2018 5:27 AM
  • User1120430333 posted


    Is that approach going to help me for the current problems?

    The approach I was thought many years ago is to keep it simple. There is nothing wrong with the repository pattern being used in a non-generic manner or not use the pattern at all nor the UoW pattern.

    http://blog.sapiensworks.com/post/2012/11/01/Repository-vs-DAO.aspx

    But you see, you should have had the database CRUD all figured out and tested before you even tried to hook up the UI/presentation layer to the backend, which would make things a whole lot more easier too, knowing that the database code is solid.

    You are aware of the information in the link, since Web applications are stateless, right?

    http://www.c-sharpcorner.com/UploadFile/d87001/connected-and-disconnected-scenario-in-entity-framework/

     

    Sunday, March 4, 2018 7:45 AM
  • User-1637592233 posted

    Thanks for your comment ...This shows i am going to be screwed up. or I had to hack my own code to make suitable with the current UI.

    Sunday, March 4, 2018 7:53 AM
  • User1120430333 posted

    It's good that you are trying to use a Repository, but maybe, you should just consider using a Data Access Layer and maybe, the DAO pattern. I'll show you the concept.

    But you should also keep in mind what is in the links and the MVC pattern.

    http://www.c-sharpcorner.com/UploadFile/56fb14/understanding-separation-of-concern-and-Asp-Net-mvc/

    https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/overview/understanding-models-views-and-controllers-cs

    <copied>

    A view should contain only logic related to generating the user interface. A controller should only contain the bare minimum of logic required to return the right view or redirect the user to another action (flow control). Everything else should be contained in the model.+

    In general, you should strive for fat models and skinny controllers. Your controller methods should contain only a few lines of code. If a controller action gets too fat, then you should consider moving the logic out to a new class in the Models folder.

    <end>

    You can view the below thread to see what I am talking about of view -- controller -- model -- DAL using DAO. 

    https://forums.asp.net/t/2137340.aspx?How+to+carry+and+check+UserID+with+another+table+to+load+up+a+specific+view+when+a+user+logs+in+

    http://www.entityframeworktutorial.net/EntityFramework5/attach-disconnected-entity-graph.aspx

    https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    The DTO(s) are in the Entities classlib project, and the MVC and the DAL have project reference to Entities and know about the DTO(s).

    Sunday, March 4, 2018 9:18 AM
  • User1400794712 posted

    Hi aakashbashyal,

    You use breakpoint to debug your project and check the model value.

    Set a breakpoint on UpdateCorporateCustomerDetail and check the model's value.

    When it comes into the breakpoint, use F10 to execute the code line by line and check the result.

    Best Regards,

    Daisy

    Monday, March 5, 2018 10:03 AM