/// <summary>
        /// Load/Refresh all Attendees for a conference
        /// </summary>
        public static void RefreshAttendees(Int64 AConferenceKey)
        {
            TDBTransaction           Transaction  = new TDBTransaction();
            bool                     SubmissionOK = true;
            PcConferenceTable        ConferenceTable;
            PUnitTable               UnitTable;
            string                   OutreachPrefix = String.Empty;
            ConferenceApplicationTDS MainDS;

            // make sure outreach codes are up to date in case it has changed in Unit record
            RefreshOutreachCode(AConferenceKey);

            DBAccess.WriteTransaction(
                ref Transaction,
                ref SubmissionOK,
                delegate
            {
                ConferenceTable = new PcConferenceTable();
                UnitTable       = new PUnitTable();
                MainDS          = new ConferenceApplicationTDS();

                // get the conference prefix which links all outreaches associated with a conference
                ConferenceTable = PcConferenceAccess.LoadByPrimaryKey(AConferenceKey, Transaction);

                if (ConferenceTable.Count == 0)
                {
                    throw new Exception("Cannot find conference " + AConferenceKey.ToString("0000000000"));
                }

                OutreachPrefix = ConferenceTable[0].OutreachPrefix;

                // load application data for all conference attendees from db
                TApplicationManagement.GetApplications(ref MainDS, AConferenceKey, OutreachPrefix, "all", -1, true, null, false);

                // check a valid pcattendee record exists for each short term application
                foreach (PmShortTermApplicationRow ShortTermAppRow in MainDS.PmShortTermApplication.Rows)
                {
                    if (!IsAttendeeValid(MainDS, OutreachPrefix, ShortTermAppRow.PartnerKey))
                    {
                        // ignore deleted applications, or cancelled applications
                        continue;
                    }

                    // update outreach code in application (it may have changed)
                    UnitTable = PUnitAccess.LoadByPrimaryKey(ShortTermAppRow.StConfirmedOption, Transaction);
                    ShortTermAppRow.ConfirmedOptionCode = ((PUnitRow)UnitTable.Rows[0]).OutreachCode;

                    // Do we have a record for this attendee yet?
                    bool AttendeeRecordExists = false;

                    if (MainDS.PcAttendee.Rows.Contains(new object[] { AConferenceKey, ShortTermAppRow.PartnerKey }))
                    {
                        AttendeeRecordExists = true;
                    }

                    // create a new PcAttendee record if one does not already exist for this attendee
                    if (!AttendeeRecordExists)
                    {
                        PcAttendeeRow AttendeeRow = MainDS.PcAttendee.NewRowTyped();

                        AttendeeRow.ConferenceKey = AConferenceKey;
                        AttendeeRow.PartnerKey    = ShortTermAppRow.PartnerKey;

                        if (ShortTermAppRow.ConfirmedOptionCode.Length >= 11)
                        {
                            AttendeeRow.OutreachType = ShortTermAppRow.ConfirmedOptionCode.Substring(5, 6);
                        }

                        PmGeneralApplicationRow GeneralAppRow = (PmGeneralApplicationRow)MainDS.PmGeneralApplication.Rows.Find(
                            new object[] { ShortTermAppRow.PartnerKey, ShortTermAppRow.ApplicationKey, ShortTermAppRow.RegistrationOffice });

                        DateTime DateAccepted = GeneralAppRow.GenAppDate;

                        if (!GeneralAppRow.IsGenAppSendFldAcceptDateNull())
                        {
                            DateAccepted = GeneralAppRow.GenAppSendFldAcceptDate.Value;
                        }
                        else if (!GeneralAppRow.IsGenAppRecvgFldAcceptNull())
                        {
                            DateAccepted = GeneralAppRow.GenAppRecvgFldAccept.Value;
                        }

                        AttendeeRow.Registered = DateAccepted;

                        // TODO: in Petra 2.x, this was calculated from pm_staff_data
                        AttendeeRow.HomeOfficeKey = ShortTermAppRow.RegistrationOffice;

                        if (AttendeeRow.HomeOfficeKey == 0)
                        {
                            AttendeeRow.HomeOfficeKey = ((int)AttendeeRow.PartnerKey / 1000000) * 1000000;
                        }

                        MainDS.PcAttendee.Rows.Add(AttendeeRow);
                    }
                }

                PcRoomAllocTable RoomAllocTable = null;
                PcExtraCostTable ExtraCostTable = null;

                // now check the other way: all attendees of this conference, are they still valid?
                foreach (PcAttendeeRow AttendeeRow in MainDS.PcAttendee.Rows)
                {
                    if ((AttendeeRow.RowState != DataRowState.Added) &&
                        !IsAttendeeValid(MainDS, OutreachPrefix, AttendeeRow.PartnerKey))
                    {
                        // remove their accommodation
                        RoomAllocTable = PcRoomAllocAccess.LoadViaPcAttendee(AttendeeRow.ConferenceKey, AttendeeRow.PartnerKey, Transaction);

                        foreach (DataRow Row in RoomAllocTable.Rows)
                        {
                            Row.Delete();
                        }

                        if (RoomAllocTable != null)
                        {
                            PcRoomAllocAccess.SubmitChanges(RoomAllocTable, Transaction);
                        }

                        // remove any extra costs
                        ExtraCostTable = PcExtraCostAccess.LoadViaPcAttendee(AttendeeRow.ConferenceKey, AttendeeRow.PartnerKey, Transaction);

                        foreach (DataRow Row in ExtraCostTable.Rows)
                        {
                            Row.Delete();
                        }

                        if (ExtraCostTable != null)
                        {
                            PcExtraCostAccess.SubmitChanges(ExtraCostTable, Transaction);
                        }

                        // remove attendee
                        AttendeeRow.Delete();
                    }
                }

                int shorttermApplicationsCount = MainDS.PmShortTermApplication.Count;
                int attendeeCount = MainDS.PcAttendee.Count;

                MainDS.ThrowAwayAfterSubmitChanges = true;

                ConferenceApplicationTDSAccess.SubmitChanges(MainDS);
            });
        }