list values changes when dataset iteration - c#

I have List of type Date_Check ,I execute a sql query and retrieve the values in a dataset
and I populate the List by iterate through the dataset ,the problem is that when the second iteration towards the list[0],list[1],list[2]... values got the replaced by current object values
Here is my code :
string query = "select Record_Id, Movie_Name from tbl_theater_master ";
DataSet dtst_Theatrs = new DataSet();
dtst_Theatrs = ObjCommon.GetObject.ExecuteQuery_Select(Connection.ConnectionString, query);
if (dtst_Theatrs.Tables[0].Rows.Count != 0)
{
List<Date_Check> lst_Date_Check = new List<Date_Check>();
Date_Check obj_Date_Check = new Date_Check();
for (int i = 0; dtst_Theatrs.Tables[0].Rows.Count > i; i++)
{
obj_Date_Check.Movie_Name = dtst_Theatrs.Tables[0].Rows[i]["Movie_Name"].ToString();
obj_Date_Check.Record_Id = dtst_Theatrs.Tables[0].Rows[i]["Record_Id"].ToString();
lst_Date_Check.Add(obj_Date_Check);
}
}
Here is my Date_Check object :
public class Date_Check
{
public string Record_Id { get; set; }
public string Movie_Name { get; set; }
}
When dataset iteration is completed the lst_Date_Check got all the indexes changed to the Last iterations values ,what's wrong with my code

Keep creation of the object of the class Date_Check obj_Date_Check = new Date_Check(); inside the for-loop. That's how you make new object on every iteration.
for (int i = 0; dtst_Theatrs.Tables[0].Rows.Count > i; i++)
{
Date_Check obj_Date_Check = new Date_Check();
obj_Date_Check.Movie_Name = dtst_Theatrs.Tables[0].Rows[i]["Movie_Name"].ToString();
obj_Date_Check.Record_Id = dtst_Theatrs.Tables[0].Rows[i]["Record_Id"].ToString();
lst_Date_Check.Add(obj_Date_Check);
}

This is because your Date_Check object is a reference type and not a value type. This means the line Date_Check obj_Date_Check = new Date_Check(); creates the variable in memory once and from then on every time update that object you are updating the same single object. You have 2 options:
Instantiate the object inside the for loop to create a single object in memory to work with i.e:
for (int i = 0; dtst_Theatrs.Tables[0].Rows.Count > i; i++)
{
Date_Check obj_Date_Check = new Date_Check();
obj_Date_Check.Movie_Name = dtst_Theatrs.Tables[0].Rows[i]["Movie_Name"].ToString();
obj_Date_Check.Record_Id = dtst_Theatrs.Tables[0].Rows[i]["Record_Id"].ToString();
lst_Date_Check.Add(obj_Date_Check);
}
Or create your Date_Check object as a Value Type by using a Struct i.e:
public struct Date_Check
{
public string Record_Id { get; set; }
public string Movie_Name { get; set; }
}

Related

Join sub variables in a List

I have my variables class with constructor
public class Gdf2Lines
{
public string line { get; set; }
public int linenumber { get; set; }
public string columnNumber { get; set; }
public string columnName { get; set; }
public Gdf2Lines()
{
line = "";
linenumber = -1;
columnNumber = ""; // prefer to keep as the string read from the text source
columnName = "";
}
}
I have my class that creates of list of the above class and populates the variables within for each line from a file
class GDF2
{
Gdf2Lines Data = new Gdf2Lines();
List<Gdf2Lines> gdf2 = new List<Gdf2Lines>();
public GDF2(string[] arrFile)
{
int count = 0;
foreach (String line in arrFile)
{
Data.line = line;
Data.linenumber = count;
Data.columnNumber = GetColumnNumber(line);
Data.columnName = GetColumnName(line);
count++;
gdf2.Add(Data);
}
}
}
I know a "normal" list can be joined into a string by:
String.Join(Environment.Newline.ToString(), List);
But is there an equally easy way to join one of the (sub) variables within my list, such as
String.Join(",", gdf2.columnName);
Currently I am using a for loop.
Something like this should work:
String.Join(",", gdf2.Select(x => x.columnName));
This uses LINQ to extract a list of columnName values from the list of Gdf2Line.

Use 'LoadfromCollection' with a list containing another list inside

My problem is that I have a list that contains a few strings and inside this list another list of decimals, something like this:
public class excelInventario
{
public excelInventario() { cols = new List<decimal>); }
public string codigo { get; set; }
public string nombre { get; set;} .
public List<decimal> cols { get; set; } //Lista de columnas
public decimal suma { get; set; }
public decimal stock { get; set; }
public decimal diferencia { get; set; }
public decimal precio { get; set; }
}
and now I need to put this in Excel. The problem is that when I use the method LoadFromCollection(MyList) the strings appear well in Excel, but the list of decimals is not put correctly, but:
System.Collections.Generic.List`1[System.Decimal].
Can I adapt this method or do I need to use a loop and put "manually" the row values one by one?
I suspect this second option it will be inefficient.
---------------EDIT TO ADD MORE CODE--------------
int tamcolumnas=excelin[0].cols.Count;
using (ExcelPackage package = new ExcelPackage(file))
{
ExcelWorksheet hoja = package.Workbook.Worksheets.Add("Comparativo unidades contadas VS stock");
hoja.Cells["A1"].Value = "CODART";
hoja.Cells["B1"].Value = "NOMBRE";
for(int i=0;i<tamcolumnas;i++)
{ hoja.Cells[1, i+3].Value = "COL"+(i+1); }
var MyList = new List<excelInventario>();
hoja.Cells.LoadFromCollection(MyList,true);
hoja.Cells[2, 3].LoadFromArrays(MyList.Select((r) => r.cols.Cast<object>).ToArray()));
in this last line is where fails.
Say:
System.ArgumentOutOfRangeException
The specified argument is outside the range of valid values.
Since those are Lists the closest you can get to automation is the LoadFromArray since those are not true objects. Its not exactly pretty since it requires casting so check for performance hits. Otherwise, it may be best to use plain old loops. Here is what I mean:
[TestMethod]
public void ListOfList_Test()
{
//http://stackoverflow.com/questions/33825995/how-to-use-loadfromcollection-in-epplus-with-a-list-containing-another-list-insi
//Throw in some data
var MyList = new List<TestExtensions.excelInventario>();
for (var i = 0; i < 10; i++)
{
var row = new TestExtensions.excelInventario
{
codigo = Path.GetRandomFileName(),
nombre = i.ToString(),
cols = new List<decimal> {i, (decimal) (i*1.5), (decimal) (i*2.5)}
};
MyList.Add(row);
}
//Create a test file
var fi = new FileInfo(#"c:\temp\ListOfList.xlsx");
if (fi.Exists)
fi.Delete();
int tamcolumnas = 10; // excelin[0].cols.Count;
using (ExcelPackage package = new ExcelPackage(fi))
{
ExcelWorksheet hoja = package.Workbook.Worksheets.Add("Comparativo unidades contadas VS stock");
hoja.Cells["A1"].Value = "CODART";
hoja.Cells["B1"].Value = "NOMBRE";
for (int i = 0; i < tamcolumnas; i++)
{
hoja.Cells[1, i + 3].Value = "COL" + (i + 1);
}
//var MyList = new List<TestExtensions.excelInventario>();
hoja.Cells.LoadFromCollection(MyList, true);
//hoja.Cells[2, 3].LoadFromArrays(MyList.Select((r) => r.cols.Cast<object>).ToArray()));
hoja.Cells[2, 3].LoadFromArrays(MyList.Select((r) => r.cols.Cast<object>().ToArray()));
package.Save();
}
}

Return List of Objects from stored procedure return data C#

I have a method that is calling a stored procedure and returning a list of objects. I am not sure how to add the result from the stored procedure to the list of objects. I tried to use model. Add but anyway I am using it I am getting error. I have identify the place I need help inside the code.
This is my code:
public List<Models.Type> get_Type(string Type_Group)
{
string connectionName = getConnectionStr();
List<Models.Type> model = null;
string myConnection = System.Configuration.ConfigurationManager.ConnectionStrings[connectionName].ToString();
SqlDatabase db = new SqlDatabase(myConnection);
using (DbCommand command = db.GetStoredProcCommand("LA_Get_Type"))
{
db.AddInParameter(command, "Type_Group", DbType.String, Type_Group);
var result = db.ExecuteReader(command);
try
{
if (result.FieldCount == 0)
model = null;
else
{
while (result.Read())
{
model = new List<Models.Type>()
{
//This is the place I don't know I tried model.Add but not sure what
to have after.
This code is when I have returning just 1 object but I want to
return list of objects
typeID = Convert.ToInt32(result["typeID"].ToString()),
type_group = result["type_group"].ToString(),
type_value = result["type_value"].ToString(),
type_desc = result["type_desc"].ToString(),
type_sort = Convert.ToInt32(result["type_sort"].ToString())
};
}
}
}
catch (Exception ex)
{
}
result.Close();
return model;
}
}
and this is my object:
public class Type
{
public int typeID { get; set; }
public string type_group { get; set; }
public string type_value { get; set; }
public string type_desc { get; set; }
public int type_sort { get; set; }
}
Change
while (result.Read())
{
model = new List<Models.Type>()
{
//This is the place I don't know I tried model.Add but not sure what
to have after.
This code is when I have returning just 1 object but I want to
return list of objects
typeID = Convert.ToInt32(result["typeID"].ToString()),
type_group = result["type_group"].ToString(),
type_value = result["type_value"].ToString(),
type_desc = result["type_desc"].ToString(),
type_sort = Convert.ToInt32(result["type_sort"].ToString())
};
}
to something like this:
model = new List<Models.Type>();
while (result.Read())
{
Models.Type aModel = new Model(){
typeID = Convert.ToInt32(result["typeID"].ToString()),
type_group = result["type_group"].ToString(),
type_value = result["type_value"].ToString(),
type_desc = result["type_desc"].ToString(),
type_sort = Convert.ToInt32(result["type_sort"].ToString())
};
model.Add(aModel);
}
Note that I'm creating a new object for each result and then adding them one by one to the list.

Create struct objects in a for loop

I have some troubls to create an struct object in for loop.
I have an UserData Struct:
public struct UserData
{
public string userID { get; set; }
public string userProjects { get; set; }
public string userAccess { get; set; }
//private List<UserData> list;
public UserData(string id,string project,string access):this()
{
this.userID = id;
this.userProjects = project;
this.userAccess = access;
// list = new List<UserData>();
}
}
So in another Class I try to make a List of my UserData Struct in a for loop:
Class ReadUserData
{
private List<UserData> userdata;
for (int j = 0; j < 4 ; j++)
{
userdata = new List<UserData>() { new
UserData(userID[j.ToString()],
userProject[j.ToString()],
useraccess[j.ToString()]) };
}
var firstuser = userdata.FirstOrDefault();
}
My Problem is that the count from the userData object is 1. It only create 1 object.
Where is my problem can you help?
Thanks
you must add objects to the list using Add method. currently you are overwriting list by putting new list into userdata
Class ReadUserData
{
private List<UserData> userdata = new List<UserData>();// create empty list
for (int j = 0; j < 4 ; j++)
{
userdata.Add(new
UserData(userID[j.ToString()],
userProject[j.ToString()],
useraccess[j.ToString()])); // add objects to the list at each iteration
}
var firstuser = userdata.FirstOrDefault();
}
More about List How to Add.
You are creating a new List<UserData> with ONE item and then you are assigning to userdata object. You are doing that repeatedly in every iteration, that's why.
Try this instead (create the list outside the loop, and Add one item at a time
Class ReadUserData
{
private List<UserData> userdata = new List<UserData>();
for (int j = 0; j < 4 ; j++)
{
userdata.Add( new
UserData(userID[j.ToString()],
userProject[j.ToString()],
useraccess[j.ToString()]) );
}
var firstuser = userdata.FirstOrDefault();
}

C# Linq "Entity with the same key '0' already added." when inserting multiple rows

I am trying to insert data in bulk, database is MySQL connection is done using Devart LinqConnect.
Here is a code:
DataContext db = new DataContext();
List<XYData> XYDList = new List<XYData>(); // Data Type
List<xydata> xyToBeInsrted = new List<xydata>(); // Database table
XYDList = XYData.genXYData(12, 1234); // Generates 12 example records
foreach (XYData oneXY in XYDList)
{
// Create clear row representation
xydata xy_row = new xydata();
// Assign data from object
xy_row.id = oneXY.Id;
xy_row.Batchid = (int)oneXY.BatchId;
xy_row.Ch = oneXY.Channel;
xy_row.Value = oneXY.Value;
xy_row.Pos = (int)oneXY.Position;
xy_row.Dtm = oneXY.Time;
// Add to list of rows to be inserted
xyToBeInsrted.Add(xy_row);
}
db.xydatas.InsertAllOnSubmit<xydata>(xyToBeInsrted);
db.SubmitChanges();
Last line gives an error "Entity with the same key '0' already added."
When I lower number of items to be generated to 1 then it works. Anything above 1 gives error.
Table has set Auto Increment on record Id field.
Trying to solve that for 2 hours without success.
EDIT:
Data Class:
public class XYData
{
[Column(IsPrimaryKey = true, IsDbGenerated = true)]
public int Id { get; set; }
public int BatchId { get; set; }
public int Channel { get; set; }
public String Value { get; set; }
public double Position { get; set; }
public DateTime Time { get; set; }
private static Random rand = new Random();
public XYData(int channel = 0, string val = "")
{
Channel = channel;
Value = val;
Position = 0;
Time = DateTime.Now;
}
public static List<XYData> genXYData(int howMany, int batchId)
{
List<XYData> _allXYData = new List<XYData>();
for (int i = 0; i < howMany; i++)
{
XYData _singleXY = new XYData();
_singleXY.BatchId = batchId;
for (int j = 64 * (1 << i); j > 0; j--)
{
uint k = (uint)rand.Next(int.MaxValue);
_singleXY.Value += k.ToString("X8");
}
_allXYData.Add(_singleXY); // Add to list
}
return _allXYData; // Return list of generated data.
}
}
Something like this may be needed on your model definition -
[Column(IsPrimaryKey=true, IsDbGenerated=true)]
public int Id { get; set; }
http://www.devart.com/linqconnect/docs/PrimaryKeyMapping.html

Categories

Resources