/// <summary>
        /// Checks if the specified row exists in the database.
        /// If it does then the table will contain the row (as well as anything else that was in it
        /// before this method was called)
        /// </summary>
        /// <param name="ordersTable"></param>
        /// <param name="orderRow"></param>
        /// <param name="ID">The ID of the order that matches the supplied one</param>
        /// <returns></returns>
        public static bool Exists(EMMADataSet.OrdersDataTable ordersTable, EMMADataSet.OrdersRow orderRow,
            ref int ID, long corpID, long charID)
        {
            bool? exists = false;
            int? orderID = 0;
            EMMADataSet.OrdersDataTable tempTable = new EMMADataSet.OrdersDataTable();
            tableAdapter.ClearBeforeFill = false;

            lock (tableAdapter)
            {
                tableAdapter.FillOrderExists(tempTable, orderRow.OwnerID, orderRow.WalletID,
                    orderRow.StationID, orderRow.ItemID, orderRow.TotalVol, orderRow.RemainingVol,
                    orderRow.Range, orderRow.OrderState, orderRow.BuyOrder, orderRow.Price, orderRow.EveOrderID,
                    ref exists, ref orderID);
            }
            if (orderID.HasValue)
            {
                if (ordersTable.FindByID(orderID.Value) == null)
                {
                    ordersTable.ImportRow(tempTable.FindByID(orderID.Value));
                }
                else
                {
                    EMMADataSet.OrdersRow existingRow = ordersTable.FindByID(orderID.Value);
                    new EMMAException(ExceptionSeverity.Warning, "market order retreived in 'Exists' is not " +
                        "unique. diagnostics follow:" +
                        "\r\n\tCharacter: " + Names.GetName(charID) +
                        "\r\n\tCorporation: " + Names.GetName(corpID) +
                        "\r\n\tOrder ID: " + orderID.Value +
                        "\r\n\tLooking for this order:" +
                        "\r\n\t\tEve order ID: " + orderRow.EveOrderID +
                        "\r\n\t\tCorp order: " + orderRow.ForCorp.ToString() +
                        "\r\n\t\tStation: " + Stations.GetStationName(orderRow.StationID) +
                        "\r\n\t\tItem: " + Items.GetItemName(orderRow.ItemID) +
                        "\r\n\t\tType: " + (orderRow.BuyOrder ? "Buy" : "Sell") +
                        "\r\n\t\tTotal volume: " + orderRow.TotalVol +
                        "\r\n\t\tRemaining volume: " + orderRow.RemainingVol +
                        "\r\n\t\tPrice: " + orderRow.Price +
                        "\r\n\t\tStatus: " + OrderStates.GetStateDescription(orderRow.OrderState) +
                        "\r\n\tAlready have this order loaded:" +
                        "\r\n\t\tEve order ID: " + existingRow.EveOrderID +
                        "\r\n\t\tCorp order: " + existingRow.ForCorp.ToString() +
                        "\r\n\t\tStation: " + Stations.GetStationName(existingRow.StationID) +
                        "\r\n\t\tItem: " + Items.GetItemName(existingRow.ItemID) +
                        "\r\n\t\tType: " + (existingRow.BuyOrder ? "Buy" : "Sell") +
                        "\r\n\t\tTotal volume: " + existingRow.TotalVol +
                        "\r\n\t\tRemaining volume: " + existingRow.RemainingVol +
                        "\r\n\t\tPrice: " + existingRow.Price +
                        "\r\n\t\tStatus: " + OrderStates.GetStateDescription(existingRow.OrderState), true);
                }
            }

            ID = orderID.HasValue ? orderID.Value : 0;
            return exists.HasValue ? exists.Value : false;
        }
        private void UpdateOrdersFromXML(CharOrCorp corc, XmlDocument fileXML)
        {
            EMMADataSet.OrdersDataTable orderData = new EMMADataSet.OrdersDataTable();
            int added = 0;
            int updated = 0;

            try
            {

                Orders.SetProcessed(corc == CharOrCorp.Corp ? _corpID : _charID, false);

                XmlNodeList orderEntries = null;
                XmlDocument xml = new XmlDocument();

                UpdateStatus(0, 1, "Getting orders from file", "", false);
                orderEntries = EveAPI.GetResults(fileXML);
                UpdateStatus(1, 1, "", orderEntries.Count + " orders found in file.", false);

                if (orderEntries != null && orderEntries.Count > 0)
                {
                    UpdateStatus(0, orderEntries.Count, "Processing orders", "", false);

                    foreach (XmlNode orderEntry in orderEntries)
                    {
                        EMMADataSet.OrdersRow orderRow = BuildOrdersRow(orderData, orderEntry, corc);
                        int id = 0;

                        if (!Orders.Exists(orderData, orderRow, ref id, _corpID, _charID))
                        {
                            // Order does not exist in the database so add it.
                            orderData.AddOrdersRow(orderRow);
                            if (orderRow.OrderState == (short)OrderState.ExpiredOrFilled)
                            {
                                bool notify = false;
                                notify = UserAccount.CurrentGroup.Settings.OrdersNotifyEnabled &&
                                    ((UserAccount.CurrentGroup.Settings.OrdersNotifyBuy && orderRow.BuyOrder) ||
                                    (UserAccount.CurrentGroup.Settings.OrdersNotifySell && !orderRow.BuyOrder));
                                if (notify)
                                {
                                    orderRow.OrderState = (short)OrderState.ExpiredOrFilledAndUnacknowledged;
                                }
                                else
                                {
                                    orderRow.OrderState = (short)OrderState.ExpiredOrFilledAndAcknowledged;
                                }
                            }
                            added++;
                        }
                        else
                        {
                            EMMADataSet.OrdersRow oldRow = orderData.FindByID(id);

                            if (oldRow.TotalVol == orderRow.TotalVol &&
                                oldRow.RemainingVol == orderRow.RemainingVol &&
                                oldRow.MinVolume == orderRow.MinVolume && oldRow.Range == orderRow.Range &&
                                oldRow.Duration == orderRow.Duration && oldRow.Escrow == orderRow.Escrow &&
                                oldRow.Price == orderRow.Price && oldRow.OrderState == orderRow.OrderState &&
                                oldRow.EveOrderID == orderRow.EveOrderID)
                            {
                                // If the order from the XML exactly matches what we have in the database
                                // then just set the processed flag and remove it from the orderData table
                                // without setting it to be removed from the database.
                                //Orders.SetProcessedByID(oldRow.ID, true);
                                orderData.RemoveOrdersRow(oldRow);
                            }
                            else
                            {
                                // Set the row to processed right now.
                                oldRow.Processed = true;
                                // Accept the changes to the row (will only be the processed flag at
                                // this point) and set the processed flag on the database.
                                // This will prevent the row from being double matched with another
                                // order later.
                                // The 'accept changes' will prevent the concurency error that we
                                // would get if we only updated the processed flag on the database
                                // side.
                                oldRow.AcceptChanges();
                                //Orders.SetProcessedByID(oldRow.ID, true);

                                // If the order was active and is now completed/expired then flag it for
                                // the unacknowledged orders viewer to display.
                                bool notify = false;
                                notify = UserAccount.CurrentGroup.Settings.OrdersNotifyEnabled &&
                                    ((UserAccount.CurrentGroup.Settings.OrdersNotifyBuy && orderRow.BuyOrder) ||
                                    (UserAccount.CurrentGroup.Settings.OrdersNotifySell && !orderRow.BuyOrder));

                                if (/*orderRow.RemainingVol == 0 &&*/
                                    orderRow.OrderState == (short)OrderState.ExpiredOrFilled &&
                                    (oldRow.OrderState == (short)OrderState.Active ||
                                    oldRow.OrderState == (short)OrderState.ExpiredOrFilled))
                                {
                                    if (notify)
                                    {
                                        oldRow.OrderState = (short)OrderState.ExpiredOrFilledAndUnacknowledged;
                                        // No longer needed as the unacknowledged orders form is displayed/refreshed
                                        // as needed when refreshing the main form after an update is complete.
                                        //if (UpdateEvent != null)
                                        //{
                                        //    UpdateEvent(this, new APIUpdateEventArgs(APIDataType.Orders,
                                        //        corc == CharOrCorp.Corp ? _corpID : _charID,
                                        //        APIUpdateEventType.OrderHasExpiredOrCompleted));
                                        //}
                                    }
                                    else
                                    {
                                        oldRow.OrderState = (short)OrderState.ExpiredOrFilledAndAcknowledged;
                                    }
                                }
                                else if (orderRow.OrderState != (short)OrderState.ExpiredOrFilled)
                                {
                                    oldRow.OrderState = orderRow.OrderState;
                                }

                                if (oldRow.TotalVol != orderRow.TotalVol ||
                                    oldRow.RemainingVol != orderRow.RemainingVol ||
                                    oldRow.MinVolume != orderRow.MinVolume || oldRow.Range != orderRow.Range ||
                                    oldRow.Duration != orderRow.Duration || oldRow.Escrow != orderRow.Escrow ||
                                    oldRow.Price != orderRow.Price || oldRow.EveOrderID != orderRow.EveOrderID)
                                {
                                    oldRow.TotalVol = orderRow.TotalVol;
                                    oldRow.RemainingVol = orderRow.RemainingVol;
                                    oldRow.MinVolume = orderRow.MinVolume;
                                    oldRow.Range = orderRow.Range;
                                    oldRow.Duration = orderRow.Duration;
                                    oldRow.Escrow = orderRow.Escrow;
                                    oldRow.Price = orderRow.Price;
                                    oldRow.EveOrderID = orderRow.EveOrderID;
                                    // Note, only other fields are 'buyOrder' and 'issued'. Neither of which we want to change.
                                    updated++;
                                }
                            }
                        }

                        UpdateStatus(added + updated, orderEntries.Count, "", "", false);
                    }
                }

                UpdateStatus(0, 0, added + " orders added to database.", "", false);
                UpdateStatus(0, 0, updated + " orders updated.", "", true);

                if (orderData.Count > 0)
                {
                    Orders.Store(orderData);
                }

                Orders.FinishUnProcessed(corc == CharOrCorp.Corp ? _corpID : _charID);
            }
            catch (Exception ex)
            {
                EMMAException emmaEx = ex as EMMAException;
                if (emmaEx == null)
                {
                    // If we've caught a standard exception rather than an EMMA one then log it by creating a
                    // new exception.
                    // Note that we don't need to actually throw it..
                    emmaEx = new EMMAException(ExceptionSeverity.Error, "Error when adding market orders", ex);
                }

                SetLastAPIUpdateError(corc, APIDataType.Orders, ex.Message);
                UpdateStatus(-1, 0, "Error", ex.Message, true);
            }

            if (UpdateEvent != null)
            {
                UpdateEvent(this, new APIUpdateEventArgs(APIDataType.Orders,
                    corc == CharOrCorp.Char ? _charID : _corpID,
                    APIUpdateEventType.UpdateCompleted));
            }
        }
        public static void Store(Order orderData)
        {
            EMMADataSet.OrdersDataTable table = new EMMADataSet.OrdersDataTable();
            EMMADataSet.OrdersRow orderRow = null;
            bool newRow = false;

            lock (tableAdapter)
            {
                tableAdapter.FillByID(table, orderData.ID);
            }

            if (table.Count == 0)
            {
                orderRow = table.NewOrdersRow();
                newRow = true;
            }
            else
            {
                orderRow = table[0];
            }

            bool corp = false;
            APICharacter charData = UserAccount.CurrentGroup.GetCharacter(orderData.OwnerID, ref corp);
            //orderRow.OwnerID = charData.CharID;
            orderRow.OwnerID = orderData.OwnerID;
            orderRow.ForCorp = corp;
            orderRow.StationID = orderData.StationID;
            orderRow.TotalVol = orderData.TotalVol;
            orderRow.RemainingVol = orderData.RemainingVol;
            orderRow.MinVolume = orderData.MinVol;
            orderRow.OrderState = orderData.StateID;
            orderRow.ItemID = orderData.ItemID;
            orderRow.Range = orderData.Range;
            orderRow.WalletID = orderData.WalletID;
            orderRow.Duration = orderData.Duration;
            orderRow.Escrow = orderData.Escrow;
            orderRow.Price = orderData.Price;
            orderRow.BuyOrder = orderData.BuyOrder;
            orderRow.Issued = orderData.Date;
            orderRow.EveOrderID = orderData.EveOrderID;
            orderRow.Processed = false;

            if (newRow)
            {
                table.AddOrdersRow(orderRow);
            }

            lock (tableAdapter)
            {
                tableAdapter.Update(table);
            }
        }
        public static EMMADataSet.OrdersDataTable LoadOrdersData(List<AssetAccessParams> accessParams, List<int> itemIDs,
            List<long> stationIDs, int state, string type)
        {
            EMMADataSet.OrdersDataTable table = new EMMADataSet.OrdersDataTable();

            if (itemIDs.Count == 0) { itemIDs.Add(0); }
            if (stationIDs.Count == 0) { stationIDs.Add(0); }
            string itemString = "";
            string stationString = "";
            foreach (int item in itemIDs) { itemString = itemString + (itemString.Length == 0 ? "" : ",") + item; }
            foreach (int station in stationIDs) { stationString = stationString + (stationString.Length == 0 ? "" : ",") + station; }
            lock (tableAdapter)
            {
                tableAdapter.FillByAny(table, AssetAccessParams.BuildAccessList(accessParams), itemString,
                    stationString, state, type);
            }

            return table;
        }
        public static decimal GetSellOrderValue(long ownerID, short walletID)
        {
            decimal retVal = 0;
            EMMADataSet.OrdersDataTable table = new EMMADataSet.OrdersDataTable();

            lock (tableAdapter)
            {
                tableAdapter.FillByAnySingle(table, ownerID, walletID, 0, 0,
                    (int)OrderState.Active, "Sell");
            }
            foreach (EMMADataSet.OrdersRow order in table)
            {
                retVal += order.Price * order.RemainingVol;
            }

            table.Clear();
            lock (tableAdapter)
            {
                tableAdapter.FillByAnySingle(table, ownerID, walletID, 0, 0,
                    (int)OrderState.OverbidAndUnacknowledged, "Sell");
            }
            foreach (EMMADataSet.OrdersRow order in table)
            {
                retVal += order.Price * order.RemainingVol;
            }

            return retVal;
        }
        public static EMMADataSet.OrdersDataTable GetOrdersByIssueDate(long ownerID, short walletID,
            DateTime earliestIsssueDate, DateTime latestIssueDate)
        {
            EMMADataSet.OrdersDataTable retVal = new EMMADataSet.OrdersDataTable();
            earliestIsssueDate = earliestIsssueDate.ToUniversalTime();
            latestIssueDate = latestIssueDate.ToUniversalTime();
            lock (tableAdapter)
            {
                tableAdapter.FillByIssueDate(retVal, ownerID, walletID, earliestIsssueDate, latestIssueDate);
            }

            return retVal;
        }
        /// <summary>
        /// Get the order used for the specified transaction. 
        /// Note that many transactions will not have orders related to them. In this case
        /// the return value will be false and the two out parameters will be null.
        /// </summary>
        /// <param name="trans"></param>
        /// <returns></returns>
        public static bool GetOrder(Transaction trans, out Order buyOrder, out Order sellOrder)
        {
            bool retVal = false;
            bool buyerForCorp = false, sellerForCorp = false;
            long buyerID =0, sellerID = 0;
            buyOrder = null;
            sellOrder = null;

            buyerID = trans.BuyerID;
            sellerID = trans.SellerID;
            APICharacter buyChar = UserAccount.CurrentGroup.GetCharacter(buyerID, ref buyerForCorp);
            APICharacter sellChar = UserAccount.CurrentGroup.GetCharacter(sellerID, ref sellerForCorp);

            EMMADataSet.OrdersDataTable table = new EMMADataSet.OrdersDataTable();
            if (buyChar != null)
            {
                if (buyerID == _lastBuyerID && trans.ItemID == _lastItemID)
                {
                    table = _lastBuyerOrders;
                }
                else
                {
                    lock (tableAdapter)
                    {
                        tableAdapter.FillByAnySingle(table, trans.BuyerID, 0, trans.ItemID, 0, 0, "Any");
                        _lastBuyerID = buyerID;
                        _lastItemID = trans.ItemID;
                        _lastBuyerOrders = table;
                    }
                }
                buyOrder = MatchOrder(table, trans);
            }
            if (sellChar != null)
            {
                table.Clear();
                if (sellerID == _lastSellerID && trans.ItemID == _lastItemID)
                {
                    table = _lastSellerOrders;
                }
                else
                {
                    lock (tableAdapter)
                    {
                        tableAdapter.FillByAnySingle(table, sellerID, 0, trans.ItemID, 0, 0, "Any");
                        _lastSellerID = sellerID;
                        _lastItemID = trans.ItemID;
                        _lastSellerOrders = table;
                    }
                }
                sellOrder = MatchOrder(table, trans);
            }

            retVal = buyOrder != null || sellOrder != null;
            return retVal;
        }
        public static decimal GetCashInEscrow(long ownerID, short walletID)
        {
            decimal retVal = 0;
            EMMADataSet.OrdersDataTable table = new EMMADataSet.OrdersDataTable();

            lock (tableAdapter)
            {
                tableAdapter.FillByAnySingle(table, ownerID, walletID, 0, 0, (int)OrderState.Active, "buy");
            }

            foreach (EMMADataSet.OrdersRow order in table)
            {
                retVal += order.Escrow;
            }
            return retVal;
        }