/// <summary>
        /// todoComment
        /// </summary>
        /// <param name="APartnerKey"></param>
        /// <param name="ASiteKey"></param>
        /// <param name="ALocationKey"></param>
        /// <param name="AReadTransaction"></param>
        /// <returns></returns>
        public static Boolean CheckHasPartnerLocationOtherPartnerReferences(Int64 APartnerKey,
            Int64 ASiteKey,
            Int32 ALocationKey,
            TDBTransaction AReadTransaction)
        {
            Boolean ReturnValue;
            PPartnerLocationTable TemplateTable;
            PPartnerLocationRow TemplateRow;
            StringCollection TemplateOperators;
            int OtherPartnerLocationReferences;

//          TLogging.LogAtLevel(9, "CheckHasPartnerLocationOtherPartnerReferences for Location " + ALocationKey.ToString());

            if (ALocationKey != 0)
            {
                // Look for other Partners that reference the specified PartnerLocation
                TemplateTable = new PPartnerLocationTable();
                TemplateRow = TemplateTable.NewRowTyped(false);
                TemplateRow.PartnerKey = APartnerKey;
                TemplateRow.SiteKey = ASiteKey;
                TemplateRow.LocationKey = ALocationKey;
                TemplateOperators = new StringCollection();
                TemplateOperators.Add("<>");
                OtherPartnerLocationReferences = PPartnerLocationAccess.CountUsingTemplate(TemplateRow, TemplateOperators, AReadTransaction);
//              TLogging.LogAtLevel(9, "CheckHasPartnerLocationOtherPartnerReferences: Location " + ALocationKey.ToString() + ": is used by " +
//                  OtherPartnerLocationReferences.ToString() + " other Partners.");
                ReturnValue = (OtherPartnerLocationReferences > 0);
            }
            else
            {
                /*
                 * Special case: for Location 0 we always return 'is referenced' - it is a
                 * dummy record (signalising 'Partner has no address') that is seen as
                 * beeing referenced all the time (even if no Partner is referencing it).
                 */
//              TLogging.LogAtLevel(9, "CheckHasPartnerLocationOtherPartnerReferences: Location " + ALocationKey.ToString() +
//                  ": is Location 0, therefore it is seen as beeing used by other Partners.");
                ReturnValue = true;
            }

            return ReturnValue;
        }
        /// <summary>
        /// Allows adding of a new Location of a FAMILY Partner to all PERSONS of that
        /// FAMILY.
        ///
        /// @comment Must only be called for Partners of Partner Class FAMILY - the
        /// function does no checks on that and will fail for other Partner Classes!
        /// </summary>
        /// <returns>void</returns>
        private static TSubmitChangesResult PerformLocationFamilyMemberPropagationChecks(PPartnerLocationRow APartnerLocationRow,
            ref PartnerAddressAggregateTDS AResponseDS,
            TDBTransaction ASubmitChangesTransaction,
            Int64 APartnerKey,
            String APartnerClass,
            ref PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable AAddressAddedPromotionDT,
            ref PPartnerLocationTable APartnerLocationTable,
            PartnerAddressAggregateTDSSimilarLocationParametersTable AExistingLocationParametersDT,
            TLocationPK[, ] ALocationReUseKeyMapping,
            out Boolean APerformPropagation,
            ref TVerificationResultCollection AVerificationResult)
        {
//          TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks for LocationKey: " + APartnerLocationRow.LocationKey.ToString() +
//                    "; AAddressAddedPromotionDT.Rows.Count: " + AAddressAddedPromotionDT.Rows.Count.ToString());

            APerformPropagation = false;
            TLocationPK SubmittedLocationPK = DetermineReplacedLocationPK(APartnerLocationRow, ALocationReUseKeyMapping);
            TLocationPK LocationPK = DetermineReplacedLocationPK(APartnerLocationRow, AExistingLocationParametersDT);

            if (CheckFamilyMemberPropagation(APartnerLocationRow, APartnerKey, APartnerClass, ref AAddressAddedPromotionDT, LocationPK,
                    ASubmitChangesTransaction))
            {
                // Check if there is a Parameter Row for the LocationKey we are looking at
                DataView PropagateLocationParametersDV = new DataView(AAddressAddedPromotionDT,
                    PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetSiteKeyDBName() + " = " + LocationPK.SiteKey.ToString() +
                    " AND " +
                    PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetLocationKeyDBName() + " = " +
                    LocationPK.LocationKey.ToString() +
                    " AND " + PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetLocationAddedDBName() + " = true AND " +
                    PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetAnswerProcessedClientSideDBName() + " = false",
                    "",
                    DataViewRowState.CurrentRows);

                if (PropagateLocationParametersDV.Count > 0)
                {
//                  TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: Location " + APartnerLocationRow.LocationKey.ToString() + ": found Family Members, decision on propagation is needed.");

                    /*
                     * More information is needed (usually via user interaction)
                     * -> stop processing here and return parameters
                     * (usually used for UI interaction)
                     */
                    if (AResponseDS == null)
                    {
//                      TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: Creating AResponseDS.");
                        AResponseDS = new PartnerAddressAggregateTDS(MPartnerConstants.PARTNERADDRESSAGGREGATERESPONSE_DATASET);
                    }

//                  TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: AAddressAddedPromotionDT.Rows.Count: " + AAddressAddedPromotionDT.Rows.Count.ToString());
                    AResponseDS.Merge(AAddressAddedPromotionDT);
//                  TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: Merged AAddressAddedPromotionDT into AResponseDS.");
//                  TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: PerformLocationFamilyMemberPropagationChecks: AResponseDS.Tables[" +
//                            MPartnerConstants.ADDRESSADDEDORCHANGEDPROMOTION_TABLENAME + "].Rows.Count: " +
//                            AResponseDS.Tables[MPartnerConstants.EXISTINGLOCATIONPARAMETERS_TABLENAME].Rows.Count.ToString());
                    return TSubmitChangesResult.scrInfoNeeded;
                }
                else
                {
//                  TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: Location " + APartnerLocationRow.LocationKey.ToString() + ": found Family Members and new Location should be propagated to them!");

                    /*
                     * Family Members were found and the new Location should be added to all
                     * of them!
                     */
                    APerformPropagation = true;

                    // Load all Persons of the Family
                    PPersonTable FamilyPersonsDT = PPersonAccess.LoadViaPFamily(APartnerKey, ASubmitChangesTransaction);

                    // Find PPartnerLocation row of the Family that we should process
                    PPartnerLocationRow FamilyPartnerLocationRow = (PPartnerLocationRow)APartnerLocationTable.Rows.Find(
                        new System.Object[] { APartnerKey, APartnerLocationRow.SiteKey,
                                              APartnerLocationRow.LocationKey });

                    if (FamilyPartnerLocationRow != null)
                    {
                        for (int Counter = 0; Counter <= FamilyPersonsDT.Rows.Count - 1; Counter += 1)
                        {
                            PPersonRow ProcessedPersonRow = FamilyPersonsDT[Counter];
//                          TLogging.LogAtLevel(9,  "PerformLocationFamilyMemberPropagationChecks: Person  " + ProcessedPersonRow.PartnerKey.ToString() + ": checking...");

                            // Check if Person doesn't already have the Location
                            if (!PPartnerLocationAccess.Exists(ProcessedPersonRow.PartnerKey, SubmittedLocationPK.SiteKey,
                                    SubmittedLocationPK.LocationKey, ASubmitChangesTransaction))
                            {
                                /*
                                 * PartnerLocation records for family members are added to APartnerLocationTable for easier data handling and
                                 * will be removed again after SubmitChanges of whole dataset but before returning to client as otherwise
                                 * they would confusingly show up on client side.
                                 */

                                // Make sure record is not added more than once to APartnerLocationTable (in case it is not yet in database).
                                if (APartnerLocationTable.Rows.Find(new System.Object[] { ProcessedPersonRow.PartnerKey, SubmittedLocationPK.SiteKey,
                                                                                          SubmittedLocationPK.LocationKey }) == null)
                                {
                                    //                              TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: Person  " + ProcessedPersonRow.PartnerKey.ToString() +
                                    //                                  ": adding Location " + SubmittedLocationPK.LocationKey.ToString() + "...");

                                    // Add a copy of the PartnerLocation data to the Person
                                    PPartnerLocationRow AddPartnerLocationRow = APartnerLocationTable.NewRowTyped(false);
                                    AddPartnerLocationRow.ItemArray = DataUtilities.DestinationSaveItemArray(AddPartnerLocationRow,
                                        FamilyPartnerLocationRow);
                                    AddPartnerLocationRow.PartnerKey = ProcessedPersonRow.PartnerKey;
                                    AddPartnerLocationRow.SiteKey = SubmittedLocationPK.SiteKey;
                                    AddPartnerLocationRow.LocationKey = SubmittedLocationPK.LocationKey;
                                    APartnerLocationTable.Rows.Add(AddPartnerLocationRow);

                                    /*
                                     * If this Person has an PartnerLocation with LocationKey 0 (this
                                     * means that this was the only PartnerLocation so far), delete the
                                     * PartnerLocation with LocationKey 0.
                                     */
                                    if (PPartnerLocationAccess.Exists(ProcessedPersonRow.PartnerKey, SubmittedLocationPK.SiteKey, 0,
                                            ASubmitChangesTransaction))
                                    {
                                        //                                  TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: Person  " + ProcessedPersonRow.PartnerKey.ToString() + ": had Location 0 assigned, deleting it.");
                                        PPartnerLocationAccess.DeleteByPrimaryKey(ProcessedPersonRow.PartnerKey,
                                            APartnerLocationRow.SiteKey,
                                            0,
                                            ASubmitChangesTransaction);
                                    }
                                }
                            }
                            else
                            {
//                              TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: Person  " + ProcessedPersonRow.PartnerKey.ToString() +
//                                      ": already has Location " + SubmittedLocationPK.LocationKey.ToString() + " assigned.");
                            }
                        }
                    }
                    else
                    {
                        throw new EOPAppException(
                            "TPPartnerAddressAggregate.PerformLocationFamilyMemberPropagationChecks: PPartnerLocation record for Family is missing");
                    }
                }
            }
            else
            {
//              TLogging.LogAtLevel(9, "PerformLocationFamilyMemberPropagationChecks: Location " + SubmittedLocationPK.LocationKey.ToString() +
//                  ": Family either has no Family Members, or no propagation of the new Location is wanted. New Location will therefore only be added to the FAMILY.");

                /*
                 * Family either has no Family Members, or it has Members, but the decision
                 * was made that the new PartnerLocation should not be added to the Family
                 * Members.
                 * The new Location will therefore only be added to the FAMILY.
                 */
            }

            return TSubmitChangesResult.scrOK;
        }
        /// <summary>
        /// For all members of the Family: if they have a PartnerLocation mapped to the
        /// same Location as the Family then update the DateGoodUntil column.
        ///
        /// @comment Must only be called for Partners of Partner Class FAMILY - the
        /// function does no checks on that and will fail for other Partner Classes!
        ///
        /// </summary>
        /// <param name="AFamilyPartnerKey">PartnerKey of the Family</param>
        /// <param name="APartnerLocationDR">PartnerLocation DataRow of the Family</param>
        /// <param name="ASubmitChangesTransaction">Running transaction in which the DB commands
        /// will be enlisted</param>
        private static void PromoteToFamilyMembersDateGoodUntilChange(Int64 AFamilyPartnerKey,
            PPartnerLocationRow APartnerLocationDR,
            TDBTransaction ASubmitChangesTransaction)
        {
            StringCollection RequiredColumns;
            PPersonTable FamilyPersonsDT;
            PPartnerLocationTable PartnerLocationDT;
            PPartnerLocationTable PartnerLocationSubmitDT;
            PPartnerLocationRow PartnerLocationSubmitDR;
            Int16 Counter;

            FamilyPersonsDT = GetFamilyMemberPartnerKeys(AFamilyPartnerKey, ASubmitChangesTransaction);
            PartnerLocationSubmitDT = new PPartnerLocationTable();
            RequiredColumns = new StringCollection();
            RequiredColumns.Add(PPartnerLocationTable.GetModificationIdDBName());

            /*
             * For all members of the Family: if they have a PartnerLocation mapped to the
             * same Location as the Family then update the DateGoodUntil column
             */
//          TLogging.LogAtLevel(9, "PromoteToFamilyMembersDateGoodUntilChange for Location " + APartnerLocationDR.LocationKey.ToString() + ": Family has " + FamilyPersonsDT.Rows.Count.ToString() + " members.");

            for (Counter = 0; Counter <= FamilyPersonsDT.Rows.Count - 1; Counter += 1)
            {
                // Load ModificationId for the PartnerLocation of each Person (otherwise we
                // will run into optimistic locking problems!)
                PartnerLocationDT = PPartnerLocationAccess.LoadByPrimaryKey(
                    FamilyPersonsDT[Counter].PartnerKey,
                    APartnerLocationDR.SiteKey,
                    APartnerLocationDR.LocationKey,
                    RequiredColumns,
                    ASubmitChangesTransaction);

                /*
                 * Check that found Person has PartnerLocation that is mapped to the same
                 * Location than the one that the PartnerLocation of the Family that we are
                 * processing is mapped to
                 */
                if (PartnerLocationDT.Rows.Count != 0)
                {
                    // Build row to be able to update that PartnerLocation
                    PartnerLocationSubmitDR = PartnerLocationSubmitDT.NewRowTyped(false);
                    PartnerLocationSubmitDR.PartnerKey = FamilyPersonsDT[Counter].PartnerKey;
                    PartnerLocationSubmitDR.SiteKey = APartnerLocationDR.SiteKey;
                    PartnerLocationSubmitDR.LocationKey = APartnerLocationDR.LocationKey;
                    PartnerLocationSubmitDR.ModificationId = PartnerLocationDT[0].ModificationId;
                    PartnerLocationSubmitDT.Rows.Add(PartnerLocationSubmitDR);

                    // Change its DateGoodUntil column to match the Family's PartnerLocation DateGoodUntil column
                    if (!APartnerLocationDR.IsDateGoodUntilNull())
                    {
                        // Make this row unchanged so that SubmitChanges later picks up a changed
                        // DataRow, and not a new DataRow.
                        PartnerLocationSubmitDR.AcceptChanges();

                        // Now change DateGoodUntil
                        PartnerLocationSubmitDR.DateGoodUntil = APartnerLocationDR.DateGoodUntil;
                    }
                    else
                    {
                        // Change DataRow to a dummy value to make Null different to what was
                        // there before
                        PartnerLocationSubmitDR.DateGoodUntil = DateTime.MinValue;
                        PartnerLocationSubmitDR.AcceptChanges();

                        // Now change DateGoodUntil
                        PartnerLocationSubmitDR.SetDateGoodUntilNull();
                    }

                    // Get PartnerLocation data of just processed Person out of memory!
                    PartnerLocationDT.Rows.Clear();
                }
            }

            /*
             * Save changes to DateGoodUntil columns if PartnerLocation of any FamilyMember got changed.
             */
            if (PartnerLocationSubmitDT.Rows.Count > 0)
            {
                // Submit the changes to the DB
                PPartnerLocationAccess.SubmitChanges(PartnerLocationSubmitDT, ASubmitChangesTransaction);
            }
        }
        /// <summary>
        /// todoComment
        /// </summary>
        /// <param name="APartnerKey"></param>
        /// <param name="ASiteKey"></param>
        /// <param name="APartnerLocationTable"></param>
        /// <param name="ATransaction"></param>
        private static void MakeSureLocation0IsNotPresent(Int64 APartnerKey,
            Int64 ASiteKey,
            PPartnerLocationTable APartnerLocationTable,
            TDBTransaction ATransaction)
        {
            PPartnerLocationTable TemplateDT;
            PPartnerLocationRow TemplateRow;

            if (APartnerLocationTable.Select(PPartnerLocationTable.GetPartnerKeyDBName() + " = " + APartnerKey.ToString() + " AND " +
                    PPartnerLocationTable.GetSiteKeyDBName() + " = " + ASiteKey.ToString() + " AND " + PPartnerLocationTable.GetSiteKeyDBName() +
                    " = 0", "",
                    DataViewRowState.Deleted).Length == 0)
            {
                TemplateDT = new PPartnerLocationTable();
                TemplateRow = TemplateDT.NewRowTyped(false);
                TemplateRow.PartnerKey = APartnerKey;
                TemplateRow.SiteKey = ASiteKey;
                TemplateRow.LocationKey = 0;

                /*
                 * Currently we need to do a count before issuing the delete command.
                 * If we don't do this, the DataStore raises a System.Data.Odbc.OdbcException
                 * if such a row doesn't exist. The DataStore should really be fixed, then
                 * counting before execution should not be necessary, which would be faster.
                 */
                if (Convert.ToInt32(PPartnerLocationAccess.CountUsingTemplate(TemplateRow, null, ATransaction)) > 0)
                {
                    PPartnerLocationAccess.DeleteUsingTemplate(TemplateRow, null, ATransaction);
//                  TLogging.LogAtLevel(9, "MakeSureLocation0IsNotPresent: Deleted PPartnerLoction that referenced Location 0.");
                }
            }
            else
            {
//              TLogging.LogAtLevel(9, "MakeSureLocation0IsNotPresent: Submitted DataSet contains a Deleted PPartnerLoction Location 0; will get deleted later.");
            }
        }