Base solution for your next web application
Open Closed

Updating many to many not working as expected #7767


User avatar
0
jtallon created

I have a course entity which has an ICollection<CourseTrainer>.

public class CourseTrainer : FullAuditedEntity
{
        public int CourseId { get; set; }
        public Course Course { get; set; }
        public int TrainerId { get; set; }
        public Trainer Trainer { get; set; }
        public virtual bool IsSignedOff { get; set; }
        public virtual DateTime? SignedOffDate { get; set; }
}

Initally I was deleting everything and then inserting everything when the user clicks save. This resulted in the record becoming IsDeleted=1 for every save and if no changes were made to the courseTrainer then the same record would be re-inserted after. This plays havok with the audit logs and makes them less readable (because if there are a lot of trainers then every time the main course is saved there would be loads of course trainer changes)

I then tried this code which works however the IsDeleted not being updated - instead, the record is deleted.

var toInsert = courseInputEntity.UserCourses.Except(savedCourse.UserCourses).ToList();
var toRemove = savedCourse.UserCourses.Except(courseInputEntity.UserCourses).ToList();

await _courseUserRepository.DeleteAsync(cu => toRemove.Any(t => t.Id == cu.UserId));

foreach (var trainee in toInsert)
{
   await _courseUserRepository.InsertAsync(trainee);
}

2 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    • is _courseUserRepository operates on CourseTrainer entity ?
    • Does that work if you delete records using foreach loop and using await _courseUserRepository.DeleteAsync(id) ?
  • User Avatar
    0
    jtallon created

    Hi ismcagdas, thanks for getting back to me. I updated the CourseTrainer entity to include

    public bool Equals(CourseTrainer other)
            {
                if (ReferenceEquals(other, null))
                {
                    return false;
                }
                if (ReferenceEquals(this, other))
                {
                    return true;
                }
                return CourseId.Equals(other.CourseId) && TrainerId.Equals(other.TrainerId);
            }
    
            public override int GetHashCode()
            {
                int hashCourseId = CourseId.GetHashCode();
                int hashTrainerId = TrainerId.GetHashCode();
                return  hashCourseId ^ hashTrainerId;
            }
    

    With the above I was then able to use the Except keyword

    private async Task UpdateCourseTrainers(Course courseInputEntity, Course savedCourse)
            {            
                var toRemove = savedCourse.CourseTrainers.Except(courseInputEntity.CourseTrainers).ToList();          
                await _courseTrainerRepository.DeleteAsync(ct => toRemove.Any(t => t.TrainerId == ct.TrainerId));
    
                var toInsert = courseInputEntity.CourseTrainers.Except(savedCourse.CourseTrainers).ToList();
                foreach (var trainer in toInsert)
                {
                    await _courseTrainerRepository.InsertAsync(trainer);
                }
            }
    

    It works well now