locked
EF add object has another object RRS feed

  • Question

  • User-1952516322 posted

    Hello,

    I have an entity "A"  that has foreign key with another entity "B".

    but why when I want to add object "A", it is required to enter values for "B" object ?

    public EntityA AddEntityA (EntityA_DTO a)
            {
                using (var scope = new TransactionScope())
                {
                    var obj = Mapper.Map<EntityA_DTO , EntityA >(a);
                    UnitOfWork.EntityA_Repository.Add(obj);
                    UnitOfWork.Save(); // Error Here >> 
                    scope.Complete();
                    return EntityA ;
                }
            }

    Error > 

    Message = "Cannot insert the value NULL into column 'Name', table 'DataBase.dbo.MyTable'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."

    The Name column is in Entity B, but I need to add object for Entity A ?

    I want to add parent object without child

    Monday, April 22, 2019 10:39 AM

Answers

  • User1520731567 posted

    Hi Khalid Salameh,

    IMHO, your model design is a bit confusing...

    Now, in Add Student, I cannot add new Student without send also the object for country or courses ????

    I think because you did not make a good relation between Students and Country.(primary,foreign key)

    You need to let the system know which country the student belongs to, without paying attention to how many courses the student has.

    So,generally,you could add drop down list about CountryId which Student belong,

    or you could try to add that Student's CountryId in controller(Although this method does not make sense),like:

     public StudentViewModel AddStudent(StudentViewModel obj)
            {
                using (var scope = new TransactionScope())
                {
                    var oStudent = Mapper.Map<StudentViewModel, Student>(obj);
    oStudent.CountryId=9; //try to add this line,test if it succeeds UOWork.StudentReposotory.Add(oStudent); UOWork.Save(); scope.Complete(); return oStudent; } }

    The key of your issue is the below model design,I make a simple one,you could refer to:

    public class Student
    {
        ...
    public int Id { get; set; }
    public string Title { get; set; }
    public string SerialNo { get; set; }
    public int CountryId { get; set; } [ForeignKey("CountryId ")] public virtual Country Country { get; set; }
    //public virtual ICollection<CoursesEntity> Courses { get; set; }//Ignore Courses temporarily } public class Country {
    public Country() { Student = new HashSet<Student>(); }
    [Key] public int CountryId { get; set; } public string Name { get; set; } public virtual ICollection<Student> Student { get; set; }
    }

    Then I suggest you could add a scaffolded item to meet your needs quickly.

     You could follow the steps below:

    Right click on Controllers -> Choose Add -> Choose 'MVC5 Controller with views, using Entity Framework', then Add-> Choose the Model (Student Model) you want to add CRUD to in 'Model class', then Add -> The controller with CRUD function is created.

     Then the  Index,Create,Details,Edit ..pages will be automatically generated.

    And you could learn more clearly how to add student with complex relationship.

    In addition,you could refer to this similar link:

    https://forums.asp.net/p/2148051/6234195.aspx?Re+How+to+Bind+SQL+foreign+key+column+to+dropdown+in+MVC+

    Best Regards.

    Yuki Tao

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 23, 2019 9:08 AM

All replies

  • User1120430333 posted


    Message = "Cannot insert the value NULL into column 'Name'

    It's telling you what is wrong that the 'Name' column in the table record cannot be null. I don't think the problem is what you think it is 

    Monday, April 22, 2019 3:26 PM
  • User1520731567 posted

    Hi Khalid Salameh,

    What is your relationship betweem entity "A" and entity "B"?

    One to One or One to Many?

    According to your descriptions,I suggest you could pay attention to model design and add navigation properties as appropriate.

    For example:

    One to One:

    public class Student
    {
        public int StudentId { get; set; }
        public string StudentName { get; set; }
    
        public virtual StudentAddress Address { get; set; } //navigation property
    }
         
    public class StudentAddress 
    {
        public int StudentAddressId { get; set; }
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string City { get; set; }
        public int Zipcode { get; set; }
        public string State { get; set; }
        public string Country { get; set; }
    
        public virtual Student Student { get; set; } //navigation property
    }

    One to Many:

    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        
        public int GradeId { get; set; } 
    //the Student entity includes foreign key property GradeId with its reference property Grade.
    //This will create a one-to-many relationship with the NotNull foreign key column in the Students table
    public Grade Grade { get; set; } //navigation property } public class Grade { public int GradeId { get; set; } public string GradeName { get; set; } public ICollection<Student> Student { get; set; } //navigation property }

    More details,you could refer to this link:

    https://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx

    Best Regards.

    Yuki Tao

    Tuesday, April 23, 2019 3:35 AM
  • User-1952516322 posted

    Hello Yuki Tao,

    Example:

    public Students()
            {
                Courses = new HashSet<CoursesEntity>();
            }
            
            public int Id { get; set; }
    public string Title { get; set; } public string SerialNo { get; set; } public int CountryId { get; set; } public virtual CountryEntity Country { get; set; } public virtual ICollection<CoursesEntity> Courses { get; set; } }

    and I have ClassViewModel  for this Student ( one for entity ,, one for ViewModel

    public partial class StudentsViewModel
        {
            public StudentsViewModel()
            {
                Country = new CountryViewModel();
                Courses = new HashSet<CoursesViewModel>();
            }
    
            public int Id { get; set; }
            public string Title { get; set; }
            public string SerialNo { get; set; }
            public int CountryId { get; set; }
    
    
    
    
            public Country CountryViewModel { get; set; }
            public ICollection<Courses> CoursesViewModel { get; set; }
    
    }

    public class Country
    {
        public Country()
        {
          Student = new HashSet<Student>();
        }
     
        public int Id { get; set; }
        public string Name { get; set; }
    
        public virtual ICollection<Student> Student { get; set; }
    
    
    
    }
    public partial class CountryViewModel 
        {
            public CountryViewModel()
            {
                Student = new HashSet<Student>();
            }    
                
            [Required]
             public int Id { get; set; }
            [Required]
            [StringLength(250)]
            public string Name { get; set; }
    
            public virtual ICollection<Student> Student { get; set; }
        }

    Now, in Add Student, I cannot add new Student without send also the object for country or courses ????

    What I want, just send an object for student to create it. 

    // In Cotroller
    
            [HttpPost]
            public ActionResult Add([FromBody]StudentViewModel objStudent)
            {
                try
                {
                    MyClass.AddStudent(objStudent);
                    return Ok(objStudent);
                }
                catch (Exception ex)
                {
                    ExceptionLogger.Log(ex);
                    return NotFound(ex.Message);
                }
            }
    
    
    ----------------------------------------
    
    // In  MyClass
    
            public StudentViewModel AddStudent(StudentViewModel obj)
            {
                using (var scope = new TransactionScope())
                {
                    var oStudent = Mapper.Map<StudentViewModel, Student>(obj);
                    UOWork.StudentReposotory.Add(oStudent);
                    UOWork.Save();
                    scope.Complete();
                    return oStudent;
                }
            }
    
    ---------------------------------------
    
    // In Reposotory
    
    _context.Student.Add(obj);

    Tuesday, April 23, 2019 7:00 AM
  • User1520731567 posted

    Hi Khalid Salameh,

    IMHO, your model design is a bit confusing...

    Now, in Add Student, I cannot add new Student without send also the object for country or courses ????

    I think because you did not make a good relation between Students and Country.(primary,foreign key)

    You need to let the system know which country the student belongs to, without paying attention to how many courses the student has.

    So,generally,you could add drop down list about CountryId which Student belong,

    or you could try to add that Student's CountryId in controller(Although this method does not make sense),like:

     public StudentViewModel AddStudent(StudentViewModel obj)
            {
                using (var scope = new TransactionScope())
                {
                    var oStudent = Mapper.Map<StudentViewModel, Student>(obj);
    oStudent.CountryId=9; //try to add this line,test if it succeeds UOWork.StudentReposotory.Add(oStudent); UOWork.Save(); scope.Complete(); return oStudent; } }

    The key of your issue is the below model design,I make a simple one,you could refer to:

    public class Student
    {
        ...
    public int Id { get; set; }
    public string Title { get; set; }
    public string SerialNo { get; set; }
    public int CountryId { get; set; } [ForeignKey("CountryId ")] public virtual Country Country { get; set; }
    //public virtual ICollection<CoursesEntity> Courses { get; set; }//Ignore Courses temporarily } public class Country {
    public Country() { Student = new HashSet<Student>(); }
    [Key] public int CountryId { get; set; } public string Name { get; set; } public virtual ICollection<Student> Student { get; set; }
    }

    Then I suggest you could add a scaffolded item to meet your needs quickly.

     You could follow the steps below:

    Right click on Controllers -> Choose Add -> Choose 'MVC5 Controller with views, using Entity Framework', then Add-> Choose the Model (Student Model) you want to add CRUD to in 'Model class', then Add -> The controller with CRUD function is created.

     Then the  Index,Create,Details,Edit ..pages will be automatically generated.

    And you could learn more clearly how to add student with complex relationship.

    In addition,you could refer to this similar link:

    https://forums.asp.net/p/2148051/6234195.aspx?Re+How+to+Bind+SQL+foreign+key+column+to+dropdown+in+MVC+

    Best Regards.

    Yuki Tao

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 23, 2019 9:08 AM
  • User-1952516322 posted

    Thanks,  After I added attribute [Key] and [ForiegnKey] it is working

    Tuesday, April 23, 2019 10:27 AM