need help! how do i update records in a many to many repository? (nhibernate in an orchard context)

Topics: Customizing Orchard, Writing modules
May 16, 2014 at 12:39 PM
Edited May 18, 2014 at 4:39 PM
Hi,

There is no content here. These are all straight repository objects, and they all have matching db tables.

Unfortunately I have no experience with nhibernate, so translating info on that in the web into the orchard implementation of it is also causing me head pain.

I'm trying to understand how I can insert/update child records through a many to many relationship.

I can query/update AttendeeRecords, query/update SessionRecords, and SessionAttendees is populated no problem.

However, I can't work out what code should go in the SetAttendees() method.

Surely this must be a common requirement, but I can't see an Orchard example anywhere, except some basic N-N documentation that won't work in this context.

This is an events module, so Sessions <- SessionAttendees -> Attendees. The Attendees may or may not already exist in the AttendeeRecord table when SetAttendees() is called.
public class SessionAttendeeRecord {
    public virtual int Id { get; set; }
    public virtual SessionRecord SessionRecord { get; set; }  // SessionRecord_Id in db 
    public virtual AttendeeRecord AttendeeRecord { get; set; } // AttendeeRecord_Id in db 
    
        // (additional columns in mapping table)
    public virtual ApprovalStatus ApprovalStatus { get; set; }
    public virtual EmailStatus EmailStatus { get; set; }    
}


public class AttendeeRecord 
{
        public AttendeeRecord() {
            SessionAttendees = new List<SessionAttendeeRecord>();
        }

        [CascadeAllDeleteOrphan, Aggregate]
        public virtual IList<SessionAttendeeRecord> SessionAttendees { get; set; }
        
        //...
}

public class SessionRecord
{
    public SessionRecord() {
        SessionAttendees = new List<SessionAttendeeRecord>();
    }

    [CascadeAllDeleteOrphan, Aggregate]
    public virtual IList<SessionAttendeeRecord> SessionAttendees { get; set; }

   
    public virtual IList<AttendeeRecord> GetAttendees() {
        return SessionAttendees.Select(x => x.AttendeeRecord).ToList();
    }
    
    public virtual IList<AttendeeRecord> SetAttendees(IList<AttendeeRecord> attendeeRecords) {
        // i would have to create/update Attendee records here and create/update SessionAttendee records that contain them
        // ???
    }               
    
    //...
}
No doubt I'm doing it wrong.
May 16, 2014 at 4:23 PM
Edited May 16, 2014 at 4:29 PM
I found a solution, though it still doesn't feel quite right, as its all a bit manual for an ORM. (This solution means I still have to create the Attendee records I want to add separately via the Attendee repository beforehand). Feels like you should just be able to simply set an Attendees property instead if you could wire it up right (i.e. with the ORM doing everything for you).
   public virtual void SetAttendees(IList<AttendeeRecord> attendeeRecords) {
        SessionAttendees.Clear();
        attendeeRecords.ForEach(AddAttendee);
    }

    public virtual void AddAttendee(AttendeeRecord attendeeRecord) {
        if (!SessionAttendees.Select(x => x.AttendeeRecord.Id == attendeeRecord.Id).Any()) {
            SessionAttendees.Add(new SessionAttendeeRecord {
                AttendeeRecord = attendeeRecord,
                ApprovalStatus = ApprovalStatus.Pending,
                EmailStatus = EmailStatus.AddedToBulkMailQueue,
                SessionRecord = this
            });
        }
    }

    public virtual void RemoveAttendee(AttendeeRecord attendeeRecord) {
        SessionAttendees.Where(x => x.AttendeeRecord == attendeeRecord)
            .ForEach(x => SessionAttendees.Remove(x));
    }