Why am I getting index out of bounds error from database - c#

I know what index out of bounds is all about. When I debug I see why as well. basically what is happening is I do a filter on my database to look for records that are potential/pending. I then gather a array of those numbers send them off to another server to check to see if those numbers have been upgraded to a sale. If it has been upgraded to a sale the server responds back with the new Sales Order ID and my old Pending Sales Order ID (SourceID). I then do a for loop on that list to filter it down that specific SourceID and update the SourceID to be the Sales Order ID and change a couple of other values. Problem is is that when I use that filter on the very first one it throws a index out of bounds error. I check the results returned by the filter and it says 0. Which i find kind of strange because I took the sales order number from the list so it should be there. So i dont know what the deal is. Here is the code in question that throws the error. And it doesn't do it all the time. Like I just ran the code this morning and it didn't throw the error. But last night it did before I went home.
filter.RowFilter = string.Format("Stage = '{0}'", Potential.PotentialSale);
if (filter.Count > 0)
{
var Soids = new int[filter.Count];
Console.Write("Searching for Soids - (");
for (int i = 0; i < filter.Count; i++)
{
Console.Write(filter[i][1].ToString() + ",");
Soids[i] = (int)filter[i][1];
}
Console.WriteLine(")");
var pendingRecords = Server.GetSoldRecords(Soids);
var updateRecords = new NameValueCollection();
for (int i = 0; i < pendingRecords.Length; i++)
{
filter.RowFilter = "Soid = " + pendingRecords[i][1];
filter[0].Row["Soid"] = pendingRecords[i][0];
filter[0].Row["SourceId"] = pendingRecords[i][1];
filter[0].Row["Stage"] = Potential.ClosedWon;
var potentialXML = Potential.GetUpdatePotentialXML(filter[0].Row["Soid"].ToString(), filter[0].Row["Stage"].ToString());
updateRecords.Add(filter[0].Row["ZohoID"].ToString(), potentialXML);
}
if i'm counting right line 17 is the error where the error is thrown. pendingRecords is a object[][] array. pendingRecords[i] is the individual records. pendingRecords[i][0] is the new Sales OrderID (SOID) and pendingRecords[i][1] is the old SOID (now the SourceID)
Any help on this one? is it because i'm changing the SOID to the new SOID, and the filter auto updates itself? I just don't know

Well I ended up changing how it worked all together and it actually sorts it a bit nicer now. The code i am about to post has a bunch of hard coded numbers due to the structure of my table that is returned. Sorry about that. I have learned since then to not do that, but i am working on a different project now and will change that when I have to change the program. But here is the solution.
var potentials = Server.GetNewPotentials(); //loads all records from server
for (int i = 0; i < potentials.Length; i++)
{
var filter = AllPotentials.DefaultView;
var result1 = CheckSoidOrSource(potentials[i].Soid, true);
var result2 = CheckSoidOrSource(potentials[i].SourceID,false) ;
//This potential can't be found at all so let's add it to our table
if (result1+result2==0)
{
Logger.WriteLine("Found new record. Adding it to DataTable and sending it to Zoho");
AllPotentials.Add(potentials[i]);
filter.RowFilter = string.Format("Soid = '{0}'", potentials[i].SourceID);
var index = AllPotentials.Rows.IndexOf(filter[0].Row);
ZohoPoster posterInsert = new ZohoPoster(Zoho.Fields.Potentials, Zoho.Calls.insertRecords);
AllPotentials.Rows[index]["ZohoID"] = posterInsert.PostNewPotentialRecord(3, filter[0].Row);
}
//This potential is not found, but has a SourceId that matches a Soid of another record.
if (result1==0 && result2 == 1)
{
Logger.WriteLine("Found a record that needs to be updated on Zoho");
ZohoPoster posterUpdate = new ZohoPoster(Zoho.Fields.Potentials, Zoho.Calls.updateRecords);
filter.RowFilter = string.Format("Soid = '{0}'", potentials[i].SourceID);
var index = AllPotentials.Rows.IndexOf(filter[0].Row);
AllPotentials.Rows[index]["Soid"] = potentials[i].Soid;
AllPotentials.Rows[index]["SourceId"] = potentials[i].SourceID;
AllPotentials.Rows[index]["PotentialStage"] = potentials[i].PotentialStage;
AllPotentials.Rows[index]["UpdateRecord"] = true;
AllPotentials.Rows[index]["Amount"] = potentials[i].Amount;
AllPotentials.Rows[index]["ZohoID"] = posterUpdate.UpdatePotentialRecord(3, filter[0].Row);
}
}
AllPotentials.AcceptChanges();
}
private int CheckSoidOrSource(string Soid, bool checkSource)
{
var filter = AllPotentials.DefaultView;
if (checkSource)
filter.RowFilter = string.Format("Soid = '{0}' OR SourceId = '{1}'",Soid, Soid);
else
filter.RowFilter = string.Format("Soid = '{0}'", Soid);
return filter.Count;
}
basically what is happening is that i noticed something about my data when I filter it this way. The two results would only return the following results (0,0) (0,1) and (1,0) (0,0) means that the record doesn't exist at all in this table so I need to add it. (1,0) means that the Sales Order ID (Soid) matches another Soid in the table so it already exists. Lastly (0,1) means that the Soid doesn't exist in this table but i found a record that has the Soid as it's source...which to me means that the one that had it as a source has been upgraded from a potential to a sale, which in turn means i have to update the record and Zoho. This worked out to much less work for me because now I don't have to search for won and lost records, i only have to search for lost records. less code same results is always a good thing :)

Related

how to generate randomly football matches in .net c#

as you can see I have ten team in my database, and here's my code, now I want to generate randomly matches in asp.net C#
in this code the problem is that "d" is a list and the return type of Data is object,
the the picture of error is below.
note in database team_id and team_name in relation when you call team id team_name will be show or call.
function is in service and service is calling in controller.
[HttpGet("DoMatch")]
public IActionResult DoMatch()
{
var res= _matchService.DoMatch();
return Ok(res);
}
public ResponseModel DoMatch()
{
var random = new Random();
List<Team> list = _context.Team.ToList();
Dictionary<int, List<Team>> d = new Dictionary<int, List<Team>> { };
var count = list.Count();
for (int i = 0; i < count / 2; i++)
{
List<Team> temp = new List<Team>();
int index1 = random.Next(list.Count);
temp.Add(list[index1]);
list.RemoveAt(index1);
int index2 = random.Next(list.Count);
temp.Add(list[index2]);
list.RemoveAt(index2);
d.Add(i, temp);
}
return new ResponseModel
{
Data = d,
IsSuccess = true
};
}
the error or exception is:
System.NotSupportedException: The collection type 'System.Collections.Generic.Dictionary2[System.Int32,System.Collections.Generic.List1[Fantasy_League.Models.Team]]' on 'FantasyLeague.Models.ViewModels.ResponseModel.Data' is not supported.
The actual problem that you're running into, as described by the exception message you're getting, is that Dictionary<int, ...> cannot be serialized to be sent back in the web response. JSON requires each key to be a string. So you'll need to decide what you actually want your model to look like. Most likely it would work just fine to use the Values from your dictionary.
Data = d.Values,
That will make the JSON data come across as an array where each element is an array with the paired teams in it.
But Fildor makes a good point in his comment, that you could do this more easily by shuffling and pairing up adjacent teams:
Data = list.OrderBy(t => random.Next()).Chunk(2);
Then all that fancy dictionary logic goes away.

Comparing two lists to see if I need to update the database or even add to

I have a simple class which holds a primary key of which I don't know what type it will be before it runs, as i'm getting the data from COM. It will either be an int or string.
I basically just need to fill up my toUpdateList & toAddList. This was working fine below with not too many records to play around with. However now the mongoDBList returns around 65k records and it's all turned very slow and it's taking 15+ minutes to resolve toUpdateList.
I'm pretty new to C# so I'm likely missing something.
I basically just need to compare one list to another and see if the RecordRevision is higher in the toUpdateList. For the toAddList this ones pretty simple as if it doesn't exist it needs to be added.
Thanks for looking I appreciate it!
class KeyRevision
{
public dynamic RecordRevision;
public dynamic PrimaryKey;
}
List<KeyRevision> potentialUpdateList = new List<KeyRevision>();
List<KeyRevision> mongoDBList = new List<KeyRevision>();
List<KeyRevision> toUpdateList = new List<KeyRevision>();
List<KeyRevision> toAddList = new List<KeyRevision>();
var sql = env.ExecuteSQL(sqlQuery);
sql.First();
// Loop over them and add to array
do
{
if (sql.RecordCount > 0)
{
//Console.WriteLine(sql.GetPropertyValue(primaryKey).ToString() + " : " + sql.RecordRevision);
var o = new KeyRevision();
o.PrimaryKey = sql.GetPropertyValue(primaryKey);
o.RecordRevision = sql.RecordRevision;
potentialUpdateList.Add(o);
}
sql.Next();
} while (!sql.EOF);
// Ask mongo for docs
var docs = collection1.Find(_ => true).Project("{RecordRevision: 1}").ToList();
// Get them into our type
mongoDBList = docs.ConvertAll(x => new KeyRevision()
{
PrimaryKey = x.GetValue("_id"),
RecordRevision = x.GetValue("RecordRevision")
});
// Finds which records we need to update
toUpdateList = potentialUpdateList.Where(x =>
mongoDBList.Any(y => y.PrimaryKey == x.PrimaryKey && y.RecordRevision < x.RecordRevision)).ToList();
// Finds the records we need to add
toAddList = potentialUpdateList.Where(x =>
mongoDBList.FindIndex(y => y.PrimaryKey == x.PrimaryKey) < 0).ToList();
Console.WriteLine($"{toUpdateList.Count} need to be updated");
Console.WriteLine($"{toAddList.Count} need to be updated");

Intuit Quickbooks Online API - How to get purchases

I'm using Intuit's .NET SDK for QBO, and am attempting to get a list of purchases from my qbo account. Here's my C# code...
var qboCashPurchaseQuery = new Intuit.Ipp.Data.Qbo.CashPurchaseQuery();
qboCashPurchaseQuery.PageNumber = 1;
qboCashPurchaseQuery.ResultsPerPage = 100;
var results = qboCashPurchaseQuery.ExecuteQuery<Intuit.Ipp.Data.Qbo.CashPurchase(context).ToList();
grdQuickBooksCustomers.DataSource = results;
I get a table with the number of records matching the number of purchases I expect, but the actual data returned is not what I need.
This is the columns and the first row of data I get back: (sorry for the formatting)
SyncToken Synchronized IdsType
0 Intuit.Ipp.Data.Qbo
This bit of code returns the same kind of weird data for some other functions such as InvoiceQuery. What am I doing wrong here to get this data? How might I actually return the detailed purchase data I need?
string q = "Select * from Purchase Where PaymentType='Cash' STARTPOSITION 1 MAXRESULTS 100";
dynamic Purchaselist = purchaseQueryService.ExecuteIdsQuery(q);
CashPurchase cashpurchase = new CashPurchase();
foreach (CashPurchase oCash in Purchaselist) {
//do something
}
var purchase = new Purchase();
var purchases = ds.FindAll(purchase, 0, 500);
That's how we query our datasets. You have to repeat the query if you've got more than 500 items.

selenium to click on several links one after other

I have a table over a webpage having many values repeating like this:
Description App Name Information
Some Desc1 App1 Some Info
Some Desc2 App2 Some Info
Some Desc3 App2 Some Info
Some Desc4 App3 Some Info
Some Desc5 App4 Some Info
At the start of my app, it will ask the user to enter an appname of their choice. What I want is if I choose APP2 it should select "Some Desc2" first, that will lead to another page and there I will do something. Then again it should come back to previous page and this time it should select "Some Desc3", that will lead to another page. This should be repeated n number of times until selenium can't find an appname specified.
I have tried as shown below:
//Finding Table, its rows and coloumns
int rowcount = driver.FindElements(By.Id("someid")).Count;
for (int i = 0; i < rowcount; i++)
{
//Finding App name based on user entered text
var elems = driver.FindElements(By.PartialLinkText(text));
IList<IWebElement> list = elems;
for (int j = 0; j < list.Count; j++)
{
var table = driver.FindElement(By.Id("someid"));
IList<IWebElement> rows = table.FindElements(By.TagName("tr"));
IList<IWebElement> cells = rows[i].FindElements(By.TagName("td"));
//Again finding element based on user entered text
var elem = driver.FindElements(By.PartialLinkText(text));
list = elem;
if (list[1].Text.Equals(text))
{
list[0].Click();
string duration;
string price;
var elements = driver.FindElements(By.Id("SPFieldNumber"));
IList<IWebElement> lists = elements;
duration = lists.First().Text.ToString();
price = lists.ElementAt(1).Text.ToString();
MessageBox.Show(duration);
MessageBox.Show(price);
driver.Navigate().Back();
}
}
}
Running this code selects "Some Desc2" correctly and everything went fine. But after returning to the previous page c# throws an exception "element not found in the cache - perhaps the page has changed since it was looked up selenium".
For this particular issue, you find table and row elements before the loop, then by calling driver.Navigate().Back(); inside the loop, your table and row are no longer in the DOM (because your page changes, DOM changes, the table element is not the one you find outside the loop anymore)
Try put them inside the loop
int rowCount = driver.FindElements(By.CssSelector("#table_id tr")).Count; // replace table_id with the id of your table
for (int i = 0; i < rowCount ; i++)
{
var table = driver.FindElement(By.Id("some ID"));
rows = table.FindElements(By.TagName("tr"));
// the rest of the code
}
However, apart from solving your problems, I really suggest you read the Selenium documentation and learn some basic C# programming first, this will save you a lot time asking questions here.
Why are you doing this every time?
var elems = driver.FindElements(By.PartialLinkText(text));
IList<IWebElement> list = elems;
// IList<IWebElement> list = driver.FindElements(By.PartialLinkText(text));
element.Text is the string type you want, no need for calling ToString()
lists.First().Text.ToString();
// lists.First().Text;
You don't need this if there's no frames involved.
driver.SwitchTo().DefaultContent();
(from your earlier post) A list of IWebElement would never equal to a string, and the result can't be an element. Avoid using var if you don't know what type you want, as it may get you a totally different thing.
IList<IWebElement> list = elems;
var elem= list.Equals(text);
(from your earlier post) element.ToString() and element.Text are different
string targetele = elem.ToString(); // you want elem.Text;

Need help in using MySqlTransaction

Hi all i would like to use MySqlTransaction in my requirement. Actually i am having a doubt regarding that i.e as per my requirement i will have to delete different values from database.
The process i am doing is as follows. Assume that i am having 2 EmpIDs where this EmpID will hold different values which may be multiple. I will store the corresponding values for that particular EmpID using Dictionary and then i will save them to a list corresponding to the EmpID.
Assume that i am having list element as follows
For EmpID 1 i will have 1,2. I will check for the maximum value from the datbase in this list if exists i would like to delete this EmpID from the database.
For EmpID 2 i will have 1,2. But in my database i will have 3 as maximum values. So this one fails . I would like to rollback the previously deleted item .
Is it possible to do with a transaction if so can any one help me in solving this
Sample i code
if(findMax(lst,iEmpID)
{
obj.delete("storeprocname"); // this will occur when my list has maximum value
}
else
{
//Here i would like to rollback my previous one referring to the delete method in class file
}
My sample code
if (findMaxPayPeriodID(lstPayPeriodID, iEmpIDs)) //Assume for the first time maxpayperiod exists and for the second time it fails how to rollback then
{
if (findSequence(lstPayPeriodID)) // Assume this is also true for first time
{
for (int ilstPayperiodID = 0; ilstPayperiodID < lstPayPeriodID1.Count; ilstPayperiodID++)
{
oAdmin.Payperiodnumber = (int)lstPayPeriodID1[ilstPayperiodID];
for (int ilistPayYear = iPayYearcnt; ilistPayYear < lstPayYear1.Count; ilistPayYear++)
{
oAdmin.PayYear = (int)lstPayYear1[ilistPayYear];
iPayYearcnt++;
break;
}
for (int ilistDateTime = idtcnt; ilistDateTime < lstDateTime1.Count; ilistDateTime++)
{
idtcnt++;
oAdmin.PaymentDate = lstDateTime1[ilistDateTime];
break;
}
}
if (oAdmin.deletePayRoll(oSqlTran))
{
oMsg.Message = "Deleted Sucessfully";
oMsg.AlertMessageBox(out m_locallblMessage);
Page.Controls.Add(m_locallblMessage);
oAdmin.FedTaxID = ddlFedTaxID.SelectedValue;
oAdmin.PayFrequency = ddlPaymentType.SelectedValue.ToString();
mlocal_strStoredProcName = "uspSearchPayRoll";
oAdmin.getPayRollDetails(out mlocal_ds, mlocal_strStoredProcName);
//grdPayroll.Visible = true;
grdPayroll.DataSource = mlocal_ds;
grdPayroll.DataBind();
if (mlocal_ds != null)
{
btnDelete.Visible = true;
}
else
btnDelete.Visible = false;
}
lstPayPeriodID.Clear();
lstDateTime.Clear();
lstPayYear.Clear();
iPayIDcnt = 0;
iPayYearcnt = 0;
idtcnt = 0;
}
else
{
rollback should be done
}
You don't provide enough information - esp. since it seems that you will use a Stored Procedure for the delete operation all bets are off...
The only option I can think of is to make sure that you find first the maximum EmpId not from one list BUT from all lists first... then just check that against the DB and act accordingly...
This way the DB will only be hit twice (for the check and for the delete/Stored Procedure)... which is definetely better in terms of scaling etc.

Categories

Resources