locked
update parent from child sum records RRS feed

  • Question

  • User-875744750 posted

    i have created solution in visual studio 2012 and this solution is layred in 4 project :

    1. project presentation layer (asp.net mvc)

    2. business entities layer

      public class Parent
      {
        public int Id {get; set;}
        public decimal TotalPrice {get; set;}
        //the rest of properties
        public private ICollection<Child> Children {get; set;}
      }
      
      public class Child
      {
        public int Id {get; set;}
        public decimal UnitePrice {get; set;}
        //the rest of properties
        public int ParentId {get; set;}
        public private Parent Parent {get; set;}
      }
    3. data access layer (ado.net data model entity framework + repositories)

      //class repository for child
      public class ParentRepository :IDisposable, IParentRepository
      {
      //implemente GetAll
         public IEnumerable<Parent>GetAllParents()
         {
            return context.parents;
         }
         public Parent GetParentById(int ParentId)
         {
            return context.Parents.Find(parentId);
         }
      
         //implemente GetAll CRUD for Parent
         public void AddParent(Parent parent)
         {
            context.Parents.Add(parent);
         }
      
         public void UpdateParent(Parent parent)
         {
            context.Parents.Attach(parent);
             context.Entry(Parents).State = EntityState.Modified;
      
         }
      
         public void DeleteParent(int parentId)
         {
            Parent parent = context.Parents.Find(parentId);
            context.Parents.Remove(parent);
         }
         // save methode
         public int Save()
         {
            return context.SaveChanges();
         }
      } 
      
      //class repository for child
      public class ChildRepository : IDisposable,IChildRepository
      {
      
      EFContext context = new EFContext();
      
      //Get the children for one parent
      
      public IEnumerable<Child> GetAllChildrenByParentId(int parentId)
      {
         var query = context.Children.Where(c=>c.ParentId == parentId)
      }
      
        //the rest of code to implemente CRUD of children
      
        public Child GetChildById(int childId)
        {
           return context.Children.Find(childId);
        }
      
        //implemente CRUD for Child
        public void AddChild(Child child)
        {
           context.Children.Add(child);
        }
      
        public void UpdateChild(Child child)
        {
          context.Children.Attach(child);
          context.Entry(child).State = EntityState.Modified;
      
        }
      
        public void DeleteChild(int childId)
        {
           Child child = context.Children.Find(childId);
           context.Children.Remove(child);
        }
        // save methode
        public int Save()
        {
           return context.SaveChanges();
        }
      }
    4. but for business logic layer in classes Bll i try to calculate the total of the Parent by sum of unit prices for the children

      public class ParentChildBll
      {
        //retreive the parent by its parentid
         public Parent GetParent(int parentId){
            using (var repository = new ParentRepository())
            {       
              return repository.GetParentById(parentId);
            }  
         }
         public decimal GetTotal(int parentId)
         {
            int total;
            //call the GetParent() methode for getting parent to update its totalprice
            Parent parent = GetParent(parentId);
            //call the methode GetAllChildrenByParentId of ChildRepository that return 
           //ienumerebal<Child> and then call the extention methode Sum for calculate 
          // the sum of unite prices of child
      
           using (var repository = new ChildRepository())
           {       
              var query = reopsitory.GetAllChildrenByParentId(parentId).Sum(d=>d.UnitePrice);
             total=query;
           }
      
           parent.TotalPrice =total;
           UpdateParent(parent);//call update parent
           return total;
       }
       //implement crud parent
       public void UpdateParent(Parent parent)
       {
         //call repository update methode in BLL class
         using (var repository = new ParentRepository())
         {       
             reopsitory.UpdateParent(parent);
             repository.Save();
         }
         //
        }
      }

    What I have tried:

    -every time i insert/update/delete child i have to call getTotal() methode for update the parent totalprice in ParentChildBLL class,

    public void AddChild(Child child)
    {
       //call repository update methode in BLL class
       using (var repository = new ChildRepository())
       {       
           reopsitory.AddChild(child);
           repository.Save();
       }
       //update totalPrice of parent each insertion of child
       getTotal(child.ParentId);
    }

    is there an implementation better for update parent total by sum of each child unitprice when the child inserted/updated/deleted

    -i don't know where do calculte sum have to be implemented, in repositories or in Bll?

    I would be grateful if you helped me

    goodby soon

    Friday, November 3, 2017 4:52 PM

All replies

  • User1120430333 posted

    The Parent and Child objects would be able to hold their states of the following:

    1) IsDirty and IsNew --- insert object to DB

    2) IsDirty and !IsNew -- update existing object in DB

    3) IsDelete -- delete object from DB.

    It can be based on what is in the link as to how you set the flags in the objectand the methods in the object to set the various states, which I have used over the years.

    http://www.dailycoding.com/Posts/maintaining_dirty_and_new_state_of_objects.aspx

    As an example, you would want the total sum to include and child objects that were in a delete status.

    parent.totalsum = (from a in parent.children.where(x = !x.IsDelete) select a.Amount).Sum();

    For the Repository, I wouldn't access EF there. It would be passed off to the DAL using the Data Access pattern.

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

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

    Of course,  the Parent and Child objects would be in project called Entities, and all projects would have reference to Entities and know what the objects were about.

    Of course, you would have to map EF entities to the Parent and Children objects and visa versa that would happen in the DAL DAO.

    So you can for instance query the Parent.Children asking for all Children objects that are !isNew and isDrity and just deal with the insert only, as an example.

    Here is an example, but its similar. It's just using dumb DTO(s) that have no state.

    dumb dto(s)  https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    using System;
    using System.Collections.Generic;
    using Entities;
    
    namespace Repository
    {
        public interface IStudentRepo
        {
            DTOStudent GetStudentById(Int32 id);
            List<DTOStudent> GetStudents();
            void CreateStudent(DTOStudent dto);
            void UpdateStudent(DTOStudent dto);
            void DeleteStudent(Int32 id);
        }
    }
    
    -----------------------------------------------------------------------------------
    
    using System;
    using System.Collections.Generic;
    using Entities;
    using DAL.DAO;
    
    namespace Repository
    {    public class StudentRepo : IStudentRepo
        {
            private IDAOStudent _daoStudent;
    
            public StudentRepo(IDAOStudent daoStudent)
            {
                _daoStudent = daoStudent;
            }
            public DTOStudent GetStudentById(int id)
            {
               return _daoStudent.GetStudentById(id);
            }
            public List<DTOStudent> GetStudents()
            {
                return _daoStudent.GetStudents();
            }
            public void CreateStudent(DTOStudent dto)
            {
                _daoStudent.CreateStudent(dto);
            }
            public void UpdateStudent(DTOStudent dto)
            {
                _daoStudent.UpdateStudent(dto);
            }
            public void DeleteStudent(int id)
            {
                _daoStudent.DeleteStudent(id);
            }
        }
    }
    

    With EF being used  in the DAL, then everything is in a disconnected state, which shows how to work with EF collections and persistence along with everything else.

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

    using System;
    using System.Collections.Generic;
    using Entities;
    
    namespace DAL.DAO
    {
        public interface IDAOStudent
        {
            DTOStudent GetStudentById(Int32 id);
            List<DTOStudent> GetStudents();
            void CreateStudent(DTOStudent dto);
            void UpdateStudent(DTOStudent dto);
            void DeleteStudent(Int32 id);
        }
    }
    
    ------------------------------------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Data.Entity; using Entities; using DAL.Model; namespace DAL.DAO { public class DAOStudent : IDAOStudent { public DTOStudent GetStudentById(Int32 id) { var dto = new DTOStudent(); using (var context = new CUDataEntities()) { var student = (context.Students.Where(a => a.StudentID == id)).SingleOrDefault(); if (student != null) { dto.StudentID = student.StudentID; dto.FirstName = student.FirstName; dto.LastName = student.LastName; dto.EnrollmentDate = student.EnrollmentDate; var enrolllments = new DAOEnrollment().GetEntrollmentsByStudentId(id).ToList(); var courses = new DAOCourse().GetCoursesByStudentCourseId(student.StudentID).ToList(); dto.EnrollsandCourses = (from a in enrolllments join b in courses on a.CourseID equals b.CourseID select new DTOEnrollandCourse() { Title = b.Title, Credits = b.Credits, Grade = a.Grade }).ToList(); } } return dto; } public void CreateStudent(DTOStudent dto) { using (var context = new CUDataEntities()) { var student = new Student { FirstName = dto.FirstName, LastName = dto.LastName, EnrollmentDate = dto.EnrollmentDate }; context.Students.Add(student); context.SaveChanges(); } } public void DeleteStudent(int id) { Student student; using (var context = new CUDataEntities()) { student = (context.Students.Where(a => a.StudentID == id)).SingleOrDefault(); } using (var newContext = new CUDataEntities()) { newContext.Entry(student).State = System.Data.Entity.EntityState.Deleted; newContext.SaveChanges(); } } public List<DTOStudent> GetStudents() { var dtos = new List<DTOStudent>(); using (var context = new CUDataEntities()) { var students = context.Students.ToList(); foreach(var stud in students) { var dto = new DTOStudent { StudentID = stud.StudentID, FirstName = stud.FirstName, LastName = stud.LastName, EnrollmentDate = stud.EnrollmentDate }; dtos.Add(dto); } } return dtos; } public void UpdateStudent(DTOStudent dto) { var student = new Student(); using (var context = new CUDataEntities()) { student = (context.Students.Where(a => a.StudentID == dto.StudentID)).SingleOrDefault(); } if (student != null) { student.FirstName = dto.FirstName; student.LastName = dto.LastName; student.EnrollmentDate = dto.EnrollmentDate; } using (var dbcontext = new CUDataEntities()) { if (student != null) { dbcontext.Entry(student).State = EntityState.Modified; dbcontext.SaveChanges(); } } } } }

     

     

    o

    Friday, November 3, 2017 6:42 PM