Ejemplo n.º 1
0
            /// <summary>
            /// Updates and immediately saves the UserDefault for the 'Last Partner Used'.
            /// </summary>
            /// <param name="APartnerKey">Partner Key of the last used Partner</param>
            /// <param name="ALastPartnerUse">Specifies which 'Last Partner Used' setting should be
            /// updated
            /// </param>
            /// <param name="APartnerClass">Partner Class of the Partner (default=<see cref="TPartnerClass.FAMILY"/>).
            /// Only relevant if <paramref name="ALastPartnerUse"/> is <see cref="TLastPartnerUse.lpuMailroomPartner"/>.</param>
            /// <returns>void</returns>
            public static void SetLastPartnerWorkedWith(Int64 APartnerKey,
                                                        TLastPartnerUse ALastPartnerUse,
                                                        TPartnerClass APartnerClass = TPartnerClass.FAMILY)
            {
                switch (ALastPartnerUse)
                {
                case TLastPartnerUse.lpuMailroomPartner:
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPARTNERMAILROOM, (object)APartnerKey);

                    if (APartnerClass == TPartnerClass.PERSON)
                    {
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                    }

                    break;

                case TLastPartnerUse.lpuPersonnelPerson:
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                    break;

                case TLastPartnerUse.lpuPersonnelUnit:
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTUNITPERSONNEL, (object)APartnerKey);
                    break;

                case TLastPartnerUse.lpuConferencePerson:
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONCONFERENCE, (object)APartnerKey);

                    // if partner is person then also set this for personnel module
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                    break;
                }
            }
Ejemplo n.º 2
0
        public static bool AddRecentlyUsedPartner(Int64 APartnerKey, TPartnerClass APartnerClass,
            Boolean ANewPartner, TLastPartnerUse ALastPartnerUse)
        {
            bool ResultValue = false;

            ResultValue = Server.MPartner.Partner.TRecentPartnersHandling.AddRecentlyUsedPartner
                              (APartnerKey, APartnerClass, ANewPartner, ALastPartnerUse);

            return ResultValue;
        }
Ejemplo n.º 3
0
            /// <summary>
            /// Updates and immediately saves the UserDefault for the 'Last Partner Used'.
            /// </summary>
            /// <param name="APartnerKey">Partner Key of the last used Partner</param>
            /// <param name="ALastPartnerUse">Specifies which 'Last Partner Used' setting should be
            /// updated
            /// </param>
            /// <returns>void</returns>
            public static void SetLastPartnerWorkedWith(Int64 APartnerKey, TLastPartnerUse ALastPartnerUse)
            {
                String        PartnerName;
                TPartnerClass PartnerClass;

                /*
                 * Store the fact that this Partner is the 'Last Partner' that was worked with
                 */

                switch (ALastPartnerUse)
                {
                case TLastPartnerUse.lpuMailroomPartner:
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPARTNERMAILROOM, (object)APartnerKey);

                    // if partner is person then also set this for personnel module
                    TServerLookup.TMPartner.GetPartnerShortName(APartnerKey, out PartnerName, out PartnerClass);

                    if (PartnerClass == TPartnerClass.PERSON)
                    {
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                    }

                    break;

                case TLastPartnerUse.lpuPersonnelPerson:
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                    break;

                case TLastPartnerUse.lpuPersonnelUnit:
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTUNITPERSONNEL, (object)APartnerKey);
                    break;

                case TLastPartnerUse.lpuConferencePerson:
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONCONFERENCE, (object)APartnerKey);

                    // if partner is person then also set this for personnel module
                    TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                    break;
                }
            }
Ejemplo n.º 4
0
            /// <summary>
            /// Updates and immediately saves the UserDefault for the 'Last Partner Used'.
            /// </summary>
            /// <param name="APartnerKey">Partner Key of the last used Partner</param>
            /// <param name="ALastPartnerUse">Specifies which 'Last Partner Used' setting should be
            /// updated
            /// </param>
            /// <returns>void</returns>
            public static void SetLastPartnerWorkedWith(Int64 APartnerKey, TLastPartnerUse ALastPartnerUse)
            {
                String PartnerName;
                TPartnerClass PartnerClass;

                /*
                 * Store the fact that this Partner is the 'Last Partner' that was worked with
                 */

                switch (ALastPartnerUse)
                {
                    case TLastPartnerUse.lpuMailroomPartner:
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPARTNERMAILROOM, (object)APartnerKey);

                        // if partner is person then also set this for personnel module
                        TServerLookup.TMPartner.GetPartnerShortName(APartnerKey, out PartnerName, out PartnerClass);

                        if (PartnerClass == TPartnerClass.PERSON)
                        {
                            TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                        }

                        break;

                    case TLastPartnerUse.lpuPersonnelPerson:
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                        break;

                    case TLastPartnerUse.lpuPersonnelUnit:
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTUNITPERSONNEL, (object)APartnerKey);
                        break;

                    case TLastPartnerUse.lpuConferencePerson:
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONCONFERENCE, (object)APartnerKey);

                        // if partner is person then also set this for personnel module
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                        break;
                }
            }
Ejemplo n.º 5
0
            /// <summary>
            /// Updates and immediately saves the UserDefault for the 'Last Partner Used'.
            /// </summary>
            /// <param name="APartnerKey">Partner Key of the last used Partner</param>
            /// <param name="ALastPartnerUse">Specifies which 'Last Partner Used' setting should be
            /// updated
            /// </param>
            /// <param name="APartnerClass">Partner Class of the Partner (default=<see cref="TPartnerClass.FAMILY"/>).
            /// Only relevant if <paramref name="ALastPartnerUse"/> is <see cref="TLastPartnerUse.lpuMailroomPartner"/>.</param>
            /// <returns>void</returns>
            public static void SetLastPartnerWorkedWith(Int64 APartnerKey,
                TLastPartnerUse ALastPartnerUse,
                TPartnerClass APartnerClass = TPartnerClass.FAMILY)
            {
                switch (ALastPartnerUse)
                {
                    case TLastPartnerUse.lpuMailroomPartner:
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPARTNERMAILROOM, (object)APartnerKey);

                        if (APartnerClass == TPartnerClass.PERSON)
                        {
                            TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                        }

                        break;

                    case TLastPartnerUse.lpuPersonnelPerson:
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                        break;

                    case TLastPartnerUse.lpuPersonnelUnit:
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTUNITPERSONNEL, (object)APartnerKey);
                        break;

                    case TLastPartnerUse.lpuConferencePerson:
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONCONFERENCE, (object)APartnerKey);

                        // if partner is person then also set this for personnel module
                        TUserDefaults.SetDefault(TUserDefaults.USERDEFAULT_LASTPERSONPERSONNEL, (object)APartnerKey);
                        break;
                }
            }
Ejemplo n.º 6
0
        /// <summary>
        /// Add Key of a recently used partner to the table that holds the keys of the
        /// recent partners.
        /// </summary>
        /// <remarks>
        /// IMPORTANT: This Method has a built-in recovery mechanism that allows it to
        /// recover from an Exception that can be thrown due to the 'Predicate Locking' implementation
        /// in PostgreSQL. If the Method makes attempts to recover from that, it
        /// ROLLS BACK THE CURRENT DB TRANSACTION so that the next SQL Command can succeed. The Method will make
        /// MAX_SUBMIT_RETRIES attempts. If the Method was called while a DB Transaction was already running
        /// then this Method will have ROLLED BACK that DB Transaction in such a case and the Method
        /// will return false!!! If the caller cares about that (i.e. if it was writing to the DB in that
        /// DB Transaction) then the caller needs to re-do the writing to the DB if this Method returns 'false'
        /// as that DB Transaction was just rolled back!
        /// </remarks>
        /// <param name="APartnerKey">Key of the partner that was recently used</param>
        /// <param name="APartnerClass"></param>
        /// <param name="ANewPartner">Indicate if the partner is a new partner</param>
        /// <param name="ALastPartnerUse">Where is the partner used?</param>
        /// <returns>returns true if handling was successful
        /// </returns>
        public static bool AddRecentlyUsedPartner(Int64 APartnerKey, TPartnerClass APartnerClass,
            bool ANewPartner, TLastPartnerUse ALastPartnerUse)
        {
            const int MAX_SUBMIT_RETRIES = 5;

            Boolean ReturnValue;
            TDBTransaction ReadAndWriteTransaction;
            Boolean NewTransaction = false;
            PPartnerTable PartnerDT;
            PRecentPartnersTable RecentPartnersDT;
            DataRowView RecentPartnersRowView;
            PRecentPartnersRow RecentPartnersRow;
            PPartnerRow PartnerRow;
            DataView RecentPartnersDV;
            string PartnerClassString;
            int Counter;
            int ClassCounter;
            int NumberOfRecentPartners;
            StringCollection FieldList;
            int SubmitRetries = 0;
            bool SubmitSuccessful = false;

            // initialize result
            ReturnValue = true;

            try
            {
                ReadAndWriteTransaction = DBAccess.GDBAccessObj.GetNewOrExistingTransaction(IsolationLevel.ReadCommitted,
                    TEnforceIsolationLevel.eilMinimum, out NewTransaction);

                if (!ANewPartner)
                {
                    PartnerDT = PPartnerAccess.LoadByPrimaryKey(APartnerKey, ReadAndWriteTransaction);

                    if (PartnerDT.Rows.Count == 0)
                    {
                        // Somehow the partner does not exist, don't add this and return here already ...
                        return false;
                    }
                }

                // At this point the partner is either new or it is not new but in existing in the db
                // Now get the class of the recently used partner.
                PartnerClassString = SharedTypes.PartnerClassEnumToString(APartnerClass);
                RecentPartnersDT = PRecentPartnersAccess.LoadViaSUser(UserInfo.GUserInfo.UserID, ReadAndWriteTransaction);

                // Check if the recently used partner already exists for the current user.
                // Add it if not, otherwise just change the timestamp.
                RecentPartnersRow = (PRecentPartnersRow)RecentPartnersDT.Rows.Find(new System.Object[] { UserInfo.GUserInfo.UserID, APartnerKey });

                if (RecentPartnersRow == null)
                {
                    RecentPartnersRow = RecentPartnersDT.NewRowTyped(true);
                    RecentPartnersRow.UserId = UserInfo.GUserInfo.UserID;
                    RecentPartnersRow.PartnerKey = APartnerKey;
                    RecentPartnersDT.Rows.Add(RecentPartnersRow);
                }

                // Change the Timestamp
                RecentPartnersRow.whenDate = DateTime.Now;
                RecentPartnersRow.whenTime = Conversions.DateTimeToInt32Time(DateTime.Now);
                RecentPartnersDV = new DataView(RecentPartnersDT);
                RecentPartnersDV.Sort = PRecentPartnersTable.GetwhenDateDBName() + " ASC, " + PRecentPartnersTable.GetwhenTimeDBName() + " ASC";
                FieldList = new StringCollection();
                FieldList.Add(PPartnerTable.GetPartnerKeyDBName());
                FieldList.Add(PPartnerTable.GetPartnerClassDBName());
                PartnerDT = PPartnerAccess.LoadViaSUserPRecentPartners(UserInfo.GUserInfo.UserID, FieldList, ReadAndWriteTransaction, null, 0, 0);

                // Get the number of recent partners that the user has set, if not found
                // take 10 as default value.
                NumberOfRecentPartners = TUserDefaults.GetInt16Default(MSysManConstants.USERDEFAULT_NUMBEROFRECENTPARTNERS, 10);
                ClassCounter = 0;

                for (Counter = RecentPartnersDV.Count - 1; Counter >= 0; Counter -= 1)
                {
                    RecentPartnersRowView = RecentPartnersDV[Counter];
                    RecentPartnersRow = (PRecentPartnersRow)RecentPartnersRowView.Row;

                    if (APartnerKey == RecentPartnersRow.PartnerKey)
                    {
                        // we don't need to check the added partner (was done already)
                        ClassCounter = ClassCounter + 1;
                    }
                    else
                    {
                        // For each recent partner we need to find out if the class matches the
                        // class of the added recent partner. Look in the table that we loaded
                        // earlier on.
                        PartnerRow = (PPartnerRow)PartnerDT.Rows.Find(RecentPartnersRow.PartnerKey);

                        if (PartnerRow == null)
                        {
                            // Partner not found. Should not happen so we delete this record to prevent
                            // future problems.
                            RecentPartnersRow.Delete();
                            continue;
                        }

                        // If the recent partners record is of a different class then don't do
                        // anything with this record.
                        if (PartnerRow.PartnerClass != PartnerClassString)
                        {
                            continue;
                        }
                        else
                        {
                            ClassCounter = ClassCounter + 1;
                        }
                    }

                    if (ClassCounter > NumberOfRecentPartners)
                    {
                        // Only keep the number of records of a certain class that the user
                        // wants to keep (find in User Defaults, otherwise use 10)
                        RecentPartnersRow.Delete();
                    }
                }

                while ((SubmitRetries < MAX_SUBMIT_RETRIES)
                       && (!SubmitSuccessful))
                {
                    try
                    {
                        // now submit the changes to the database
                        PRecentPartnersAccess.SubmitChanges(RecentPartnersDT, ReadAndWriteTransaction);

                        SubmitSuccessful = true;
                    }
                    catch (Npgsql.NpgsqlException Exc)
                    {
                        // Check if we ran into the error 'could not serialize access due to read/write dependencies among transactions'
                        // which has error code 40001. This is due to the 'Predicate Locking' implementation in PostgreSQL.
                        // If so, retry, as this should overcome the error condition!
                        // (See http://stackoverflow.com/questions/12837708/predicate-locking-in-postgresql-9-2-1-with-serializable-isolation)
                        // That error has been encountered with the 'PetraMultiStart' test program where many clients may open a Partner Edit
                        // at nearly the same time, but it could be encountered in a 'real office scenario' as well when two users open a
                        // Partner Edit screen at nearly the same time.
                        if (String.Compare(Exc.Code, "40001") == 0)
                        {
//                            TLogging.LogAtLevel(0, "TRecentPartnersHandling.AddRecentlyUsedPartner: We need to retry issuing SubmitChanges as the RDBMS suggested to do that when 'Predicate Locking' failed (PostgreSQL Error Code 40001).");

//                            TLogging.LogAtLevel(0, "TRecentPartnersHandling.AddRecentlyUsedPartner: rolling back DB Transaction to allow further SQL Commands to succeed");
                            DBAccess.GDBAccessObj.RollbackTransaction();
//                            TLogging.LogAtLevel(0, "TRecentPartnersHandling.AddRecentlyUsedPartner: rolled back DB Transaction, now starting a new DB Transaction");

                            // Let the caller of this Method know that the Method has rolled back the DB Transaction that was started outside of this Method.
                            // If the caller cares about that (i.e. if it was writing to the DB in that DB Transaction) then the caller needs to re-do the
                            // writing to the DB if this Method returns 'false' as that DB Transaction was just rolled back!
                            if (!NewTransaction)
                            {
                                ReturnValue = false;
                            }

                            SubmitRetries++;

                            ReadAndWriteTransaction = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.ReadCommitted, 2);
//                            TLogging.LogAtLevel(0, "TRecentPartnersHandling.AddRecentlyUsedPartner: successfully started a new DB Transaction, now retrying SubmitChanges (Retry attempt number: " + SubmitRetries.ToString() + ")...");

                            // Now let the while statement retry the submitting!
                        }
                        else
                        {
                            throw;
                        }
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                    finally
                    {
                        if ((SubmitSuccessful)
                            && (SubmitRetries > 0))
                        {
                            TLogging.LogAtLevel(0,
                                "TRecentPartnersHandling.AddRecentlyUsedPartner: SubmitChanges was successful after " + SubmitRetries.ToString() +
                                " retry attempts (we recovered from the 'Predicate Locking' error that PostgreSQL issued [PostgreSQL Error Code 40001])!");
                        }
                        else if (SubmitRetries > MAX_SUBMIT_RETRIES)
                        {
                            TLogging.LogAtLevel(0,
                                "TRecentPartnersHandling.AddRecentlyUsedPartner: SubmitChanges was NOT successful after " +
                                SubmitRetries.ToString() +
                                " retry attempts (we FAILED TO RECOVER from the 'Predicate Locking' error that PostgreSQL issued [PostgreSQL Error Code 40001])!");
                        }
                    }
                }
            }
            finally
            {
                if (NewTransaction)
                {
                    DBAccess.GDBAccessObj.CommitTransaction();

                    TLogging.LogAtLevel(0, "TRecentPartnersHandling.AddRecentlyUsedPartner: committed own transaction.");
                }
            }

            return ReturnValue;
        }