Foreach IndexOutOfRangeException - c#

I tried already some Solutions from here.. without success!
This is my code and the error message below,
SQLite.SQLiteConnection connection = new SQLite.SQLiteConnection(dbPath);
using (var db = new SQLite.SQLiteConnection(dbPath))
{
int i = 0;
var d = from x in db.Table<stations>() select x;
foreach (var sd in d)
{
pushpin[] Tanke = new pushpin[i];
Tanke[i].Titel = sd.name.ToString(); //IndexOutOfRangeException (see below)
Tanke[i].Text = sd.brand.ToString();
Tanke[i].longitude = sd.longitude;
Tanke[i].latitude = sd.latitude;
MapLayer.SetPosition(Tanke[i], new Location(Tanke[i].latitude, Tanke[i].longitude));
pinLayer.Children.Add(Tanke[i]);
ToolTipService.SetToolTip(Tanke[i], Tanke[i].Titel);
i++;
}
db.Dispose();
db.Close();
}

You are creating an array of zero elements when i is zero.
pushpin[] Tanke = new pushpin[i];
Tanke[i].Titel = sd.name.ToString();
Then you access the first element using [0]. That won't work. There is no element in a zero element array.

The problem is how you are creating your array of pushpin. It doesn't look like you need the array so do this instead:
SQLite.SQLiteConnection connection = new SQLite.SQLiteConnection(dbPath);
using (var db = new SQLite.SQLiteConnection(dbPath))
{
var d = from x in db.Table<stations>() select x;
foreach (var sd in d)
{
var tmp = new pushpin();
tmp.Titel = sd.name.ToString(); //IndexOutOfRangeException (see below)
tmp.Text = sd.brand.ToString();
tmp.longitude = sd.longitude;
tmp.latitude = sd.latitude;
MapLayer.SetPosition(tmp, new Location(tmp.latitude, tmp.longitude));
pinLayer.Children.Add(tmp);
ToolTipService.SetToolTip(tmp, tmp.Titel);
}
db.Dispose();
db.Close();
}

While you are stepping over entries in a foreach and create each time a Array of zero elements ( i = 0 ) you can't save something becauste the [0] element is not existing

Related

SaveChanges() inside foreach, to get ID inserted

I'm trying to insert inside a foreach and then get the ID inserted to insert this ID in another table (head and detail). And I have 2 foreach inside another. I'm using entity framework.
var remisiones = dbLocal.Database.SqlQuery<datosConsulta>(qDocumento).ToList();
foreach (var x in remisiones)
{
var bcDoc = new bcDocumentos();
bcDoc.cfecha = Convert.ToDateTime(x.CFECHA);
dbLocal.bcDocumentos.Add(bcDoc);
dbLocal.SaveChanges();
int idBcDocumento = bcDoc.id_documento; // I NEED TO GET THIS ID INSERTED
foreach (var z in movimientos)
{
var bcMovs = new bcMovimientos();
bcMovs.id_documento = idBcDocumento; // TO INSERT HERE IN THE DETAIL TABLE
dbLocal.bcMovimientos.Add(bcMovs);
dbLocal.SaveChanges();
int idBcMovimiento = bcMovs.id_movimiento; // AND THEN GET THE NEW ID FO THE DETAIL
}
}
If you have specified the id_documento field in the database as Identity, you can use the following code, otherwise change id_documento to Identity.
int idBcDocumento = dbLocal.bcDocumentos.OrderByDescending(p => p.id_documento).First().id_documento;
full code
var remisiones = dbLocal.Database.SqlQuery<datosConsulta>(qDocumento).ToList();
foreach (var x in remisiones)
{
var bcDoc = new bcDocumentos();
bcDoc.cfecha = Convert.ToDateTime(x.CFECHA);
dbLocal.bcDocumentos.Add(bcDoc);
dbLocal.SaveChanges();
int idBcDocumento = dbLocal.bcDocumentos.OrderByDescending(p => p.id_documento).First().id_documento; // I NEED TO GET THIS ID INSERTED
foreach (var z in movimientos)
{
var bcMovs = new bcMovimientos();
bcMovs.id_documento = idBcDocumento; // TO INSERT HERE IN THE DETAIL TABLE
dbLocal.bcMovimientos.Add(bcMovs);
dbLocal.SaveChanges();
int idBcMovimiento = dbLocal.bcMovs.OrderByDescending(p => p.id_movimiento).First().id_movimiento; // AND THEN GET THE NEW ID FO THE DETAIL
}
}

csvHelper Put values from different lines into one filed in Database

I have a .csv file structured like so, first row is the header column, for each SomeID I need to add the NetCharges together(or substract if the code calls for it) and put each item into its own column by the SomeCode column.
Heres the file I receive;
SomeID,OrderNumber,Code,NetCharge,Total
23473,30388,LI 126.0000, 132.00
96021, 000111, LI, 130.00, 126.00
23473,30388,FU 6.0000, 132.00
4571A,10452,LI,4100.0000, 4325.0000
4571A,10452,FU,150.00,4325.0000
4571A,10452,DT,75.00,4325.0000
I need to insert the data to my sql table which is structured like this. This is what I'm aiming for:
ID OrderNumber LICode LICodeValue FUCode FUCodeValue DTCode, DTCodeValue, total
23473 30388n LI 126.000 FU 6.0000 NULL NULL 132.0000
4571A 10452 LI 4100.0000 FU 150.0000 DT 75.00 4325.0000
My SomeID will not always be grouped together like the 4571A id is.I basically need to iterate over this file and create one record for each SomeID. I cannot seem to find a way with csvHelper. I'm using C# and csvHelper. I have trid this so far but I cannot get back to the SomeId after passing on to the nexr one:
using (var reader = new StreamReader( "C:\testFiles\some.csv" ))
using (var csv = new CsvReader( reader, CultureInfo.InvariantCulture ))
{
var badRecords = new List<string>();
var isRecordBad = false;
csv.Configuration.HasHeaderRecord = true;
csv.Configuration.HeaderValidated = null;
csv.Configuration.IgnoreBlankLines = true;
csv.Configuration.Delimiter = ",";
csv.Configuration.BadDataFound = context =>
{
isRecordBad = true;
badRecords.Add( context.RawRecord );
};
csv.Configuration.MissingFieldFound = ( s, i, context ) =>
{
isRecordBad = true;
badRecords.Add( context.RawRecord );
};
List<DataFile> dataFile = csv.GetRecords<DataFile>().ToList();
//initialize variable
string lastSomeId = "";
if (!isRecordBad)
{
foreach (var item in dataFile)
{
// check if its same record
if (lastSomeId != item.SomeID)
{
MyClass someClass = new MyClass();
lastSomeId = item.SomeID;
//decimal? LI = 0;//was going to use these as vars for calculations not sure I need them???
//decimal? DSC = 0;
//decimal? FU = 0;
someClass.Id = lastSomeId;
someClass.OrdNum = item.OrderNumber;
if (item.Code == "LI")
{
someClass.LICode = item.Code;
someClass.LICodeValue = item.NetCharge;
}
if (item.Code == "DT")
{
someClass.DTCode = item.Code;
someClass.DTCodeValue = item.NetCharge
}
if (item.Code == "FU")
{
someClass.FUCode = item.Code;
someClass.FUCodeValue = item.NetCharge;
}
someClass.Total = (someClass.LICodeValue + someClass.FUCodeValue);
//check for other values to calculate
//insert record to DB
}
else
{
//Insert into db after maipulation of values
}
}
}
isRecordBad = false;
}//END Using
Any clues would be greatly appreciated. Thank you in advance.

Concatenating lists horizontally C#

I'm using the CsvHelper library tool to help write lists that I've created to CSV file.
using (var sr = new StreamReader(inPath))
{
using (var sw = new StreamWriter(outPath))
{
var reader = new CsvReader(sr);
var writer = new CsvWriter(sw);
IEnumerable records = reader.GetRecords<DataRecord>().ToList();
List<CountAndFrequencyClass> list1 = new List<CountAndFrequencyClass>();
list1 = CountAndFrequency(records, "ShipperName", 1);
List<CountAndFrequencyClass> list2 = new List<CountAndFrequencyClass>();
list2 = CountAndFrequency(records, "ShipperCity", 1);
list1 = list1.Concat(list2).ToList();
writer.WriteRecords(list2);
}
}
The list1=list1.Concat(list2).ToList(); does indeed concatenate the strings, but it stacks them on top of each other when they're written out to the CSV file. I want to find a way to concatenate the lists horizontally (so they're displayed next to eachother) instead of vertically.
Thanks for any help and please let me know if additional information is needed!
You can use a loop to add list2 column to records of list1
foreach (var i=0 ; i< list1.Count; i++)
{
if(i>=list2.Count ) break;
var rec1 = list1[i];
var rec2 = list2[i];
rec1.NewColumn = rec2.ColumnToAdd;
}
You could write them to the file as you loop through the lists.
using (var sr = new StreamReader(inPath))
{
using (var sw = new StreamWriter(outPath))
{
var reader = new CsvReader(sr);
var writer = new CsvWriter(sw);
IEnumerable records = reader.GetRecords<DataRecord>().ToList();
List<CountAndFrequencyClass> list1 = new List<CountAndFrequencyClass>();
list1 = CountAndFrequency(records, "ShipperName", 1);
List<CountAndFrequencyClass> list2 = new List<CountAndFrequencyClass>();
list2 = CountAndFrequency(records, "ShipperCity", 1);
for (int i = 0; i < list1.Count; i++)
{
writer.WriteRecord(list1[i]);
writer.WriteRecord(list2[i]);
writer.NextRecord();
}
}
}

Compare Two Complex List of data

When I am Trying to save current list of data into database, I need to get already existing data from database, and need to compare with current list of data.
I have two lists one is PreviousList(existing data from DB) and other is CurrentList(Modified data)
public class SoftClose
{
public int ID = -1;
public int AID = -1;
public int WFID = -1;
public string PREFIX;
public DateTime SCDATE;
public string STATUS;
}
In CurrentList I modified Prefix to D2 where ID=1 and added new row(Id=4)...
My req is
When I am trying to save CurrentList to Db,
If there is any new Prefix in CurrentList that is not there in PreviousList I need to insert that new row and need to change Status to ADD for that row.
I changed Prefix to D2 where Id = 1 in CurrentList. D1 is there is DB and but not in CurrentList so i need to delete it. So i need to change the status to DELETE for that record. I should not insert D2 record where id=1 becuase D2 is already there. If I changed to D5 where Id = 1 then I need to insert it because D5 is not there in DB So i need to change the status to UPDATE.
How to do this? What is the best approach to compare lists
here is a solution you could try:
List<SoftClose> previousList = new List<SoftClose>(){
new SoftClose(){ID=1, Status = "NO_CHANGE",AID="19", Prefix = "D1"},
new SoftClose(){ID=2, Status = "NO_CHANGE",AID="20", Prefix = "D2"},
new SoftClose(){ID=3, Status = "NO_CHANGE",AID="21", Prefix = "D3"}
};
List<SoftClose> currentList = new List<SoftClose>(){
new SoftClose(){ID=1, Status = "NO_CHANGE",AID="19", Prefix = "D2"},
new SoftClose(){ID=2, Status = "NO_CHANGE",AID="20", Prefix = "D2"},
new SoftClose(){ID=3, Status = "NO_CHANGE",AID="21", Prefix = "D6"},
new SoftClose(){ID=4, Status = "NO_CHANGE",AID="22", Prefix = "D4"},
new SoftClose(){ID=5, Status = "NO_CHANGE",AID="22", Prefix = "D5"}
};
var addlist = currentList.Where(c => previousList.All(p => !p.ID.Equals(c.ID) && !p.Prefix.Equals(c.Prefix)));
foreach(var n in addlist)
{
var index = currentList.FindIndex(p => p.Prefix.Equals(n.Prefix));
currentList[index].Status = "ADD";
}
var updateORdeletelist = currentList.Where(c => c.Status.Equals("NO_CHANGE") && previousList.Exists(p => p.ID.Equals(c.ID) && !p.Prefix.Equals(c.Prefix)));
foreach (var n in updateORdeletelist)
{
var index = currentList.FindIndex(p => p.Prefix.Equals(n.Prefix));
if (previousList.FindIndex(p => p.Prefix.Equals(n.Prefix)) < 0)
currentList[index].Status = "UPDATE";
else
currentList[index].Status = "DELETE";
}
foreach (var item in currentList)
{
Console.WriteLine($"Id:{item.ID}, Desc1:{item.Prefix}, Status:{item.Status}");
}
output
Id:1, Desc1:D2, Status:DELETE
Id:2, Desc1:D2, Status:NO_CHANGE
Id:3, Desc1:D6, Status:UPDATE
Id:4, Desc1:D4, Status:ADD
Id:5, Desc1:D5, Status:ADD
There is a tool called Side by Side SQL Comparer in C# at https://www.codeproject.com/Articles/27122/Side-by-Side-SQL-Comparer-in-C.
basic use of the component:
using (TextReader tr = new StreamReader(#"c:\1.sql"))
{
sideBySideRichTextBox1.LeftText = tr.ReadToEnd();
}
using (TextReader tr = new StreamReader(#"c:\2.sql"))
{
sideBySideRichTextBox1.RightText = tr.ReadToEnd();
}
sideBySideRichTextBox1.CompareText();
You load the left and right sides to their respective variables sideBySideRichTextBox1.LeftText and sideBySideRichTextBox1.RightText and compare them with sideBySideRichTextBox1.CompareText();
In your case the 1.sql and 2.sql would be your PreviousList and CurrentList -database files.
There is more detailed documentation at the project-site.

How to avoid repeating when I get data from stored procedure?

I get a list from stored procedure with its child date I want to avoid repeating when I add items to the the list
Here is my code:
var cmd = db.Database.Connection.CreateCommand();
cmd.CommandText = "[dbo].[T]";
db.Database.Connection.Open();
var reader1 = cmd.ExecuteReader();
var objectContext1 = ((IObjectContextAdapter)db).ObjectContext;
var usersLi = objectContext1.Translate<GetAllNewsForUser>(reader1).ToList();
List<GetAllNewsForUser> lll = new List<GetAllNewsForUser>();
foreach (var item in usersLi)
{
NewsInfo newsInfo = new NewsInfo();
GetAllNewsForUser g = new GetAllNewsForUser();
g.UserName = item.UserName;
NewsInfo nnn = new NewsInfo();
nnn.NewsTitle = item.NewsTitle;
nnn.NewsId = item.NewsId;
g.NewsInfos.Add(nnn);
lll.Add(g);
}
are there any unique identifiers for g, for example a user Id. in which case you could easily use the following:
if (!lll.Any(x=>x.UserId ==g.UserId)) //include system.linq
{
lll.Add(g);
}
You could also look at modifying your stored procedure to not return duplicates.
EDIT ----
Just twigged as to what you actually after, sorry.....
Its just a rough draft but i think this is what you require.
List<GetAllNewsForUser> lll = new List<GetAllNewsForUser>();
foreach (var item in usersLi)
{
NewsInfo nnn = new NewsInfo();
nnn.NewsTitle = item.NewsTitle;
nnn.NewsId = item.NewsId;
if (!lll.Any(x=> x.UserName == item.UserName)
{
GetAllNewsForUser g = new GetAllNewsForUser();
g.UserName = item.UserName;
g.NewsInfos.Add(nnn);
lll.Add(g);
}
else
{
lll.Where(x=>x.UserName == item.Username).FirstOrDefault().NewsInfos.Add(nnn)
}
}
From what I understand so far, you are trying to avoid adding same rows in the list(based on value of some column).
LINQ might help here.
usersLi.GroupBy(e => new {
UserID = e.UserUD
}).Select(g => g.First());

Categories