store array in data contract - c#

i have a data contract defined as follows:
[DataContract]
public class DemoSearchList : ReturnValuesBase
{
[DataMember]
public string SessionId { get; set; }
[DataMember]
public string[] StartDate { get; set; }
[DataMember]
public string[] EndDate { get; set; }
[DataMember]
public string ProductID { get; set; }
}
as u can observe StartDate and Enddate are array of strings.
i want to send array of responses to these.
for (int i = 0; i < DS.Tables[0].Rows.Count; i++)
{
DemoSearchList.StartDate[i] = Convert.ToString(DS.Tables[0].Rows[i][0]);
DemoSearchList.EndDate[i] = Convert.ToString(DS.Tables[0].Rows[i][1]);
}
DS is a dataset.
but i get an error as index out of bound . can anyone please help and also tel me if anything extra needs to be declared and used to achieve this

This means that your array is has not the correct size or is not yet initialized. You need to do this before your for-loop:
DemoSearchList.StartDate = new string[DS.Tables[0].Rows.Count];
DemoSearchList.EndDate = new string[DS.Tables[0].Rows.Count];
But I would prefer to make a list instead of an array (if you don't need the index of each value):
[DataContract]
public class DemoSearchList : ReturnValuesBase
{
public DemoSearchList()
{
this.StartDate = new List<string>();
this.EndDate = new List<string>();
}
[DataMember]
public List<string> StartDate { get; set; }
[DataMember]
public List<string> EndDate { get; set; }
}
Then your for-loop could look like this:
for (int i = 0; i < DS.Tables[0].Rows.Count; i++)
{
DemoSearchList.StartDate.Add(Convert.ToString(DS.Tables[0].Rows[i][0]));
DemoSearchList.EndDate.Add(Convert.ToString(DS.Tables[0].Rows[i][1]));
}

For using Array their length should be defined
StartDate = new String[10]; //can use data row count here
EndDate = new String[10]; //can use data row count here
if you want to use objects of dynamic length then use LISTinstead
or change them to
[DataMember]
public List<String> StartDate { get; set; }
[DataMember]
public List<String> EndDate { get; set; }

Related

What's the most efficient way of using AutoMapper to update / append to array?

I have an array of a class MyClassDTO that needs to be used to update items in the MyClass array:
public class MyClass
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
}
public class MyClassDTO
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
}
I was thinking using a dictionary to store the values from the DB and, then, iterate over the updated values and either update an existing value or create a new one. Something like this:
public void UpdateMyClassArray(IEnumerable<MyClassDTO> myClassDTOArray)
{
var currentValuesInDB = GetArray();
var myDictionary = new Dictionary<int, MyClass>();
foreach (var myClass in currentValuesInDB)
myDictionary.Add(myClass.Id, myClass);
var updatedMyClasses = myClassDTOArray
.Select(myClassDTO =>
{
if (myClassDTO.Id is null)
return Mapper.Map<MyClass>(myClassDTO);
int id = myClassDTO.Id.Value;
if (!myDictionary.ContainsKey(id))
return Mapper.Map<MyClass>(myClassDTO);
var storedMyClass = myDictionary[id];
return Mapper.Map(myClassDTO, storedMyClass);
});
SaveChanges(updatedMyClasses);
}
My question is: is there a better way of doing this? Does AutoMapper provide a built-in method for dealing with this case?

Convert List<T> to Array in C#

I have a list derived from
public class main
{
public list<myclass> data { get; set; }
}
public class myclass
{
public string variety { get; set; }
public string ordertype { get; set; }
public string producttype { get; set; }
}
Now I want to convert the List to return an array for VBA interop, how can I loop through my class in a single statement to convert all elements to array in one go. I have a few other classes that have a huge number of elements. I've tried the below code, but it's throwing out of bound error. I need to automatically loop through elements in myclass and assign it to array and so on. Is there any alternative/one-liner statement for this to convert the entire list to array.
string[] NamesArray = new string[list.Count];
string[] NamesArray2 = new string[] { };
for (int i = 0; i < NamesArray.Length; i++)
{
int idx = 0;
NamesArray[i] = bres.data[i].ToString();//here I am getting the myclass list not the elements inside the myclass.
foreach (var k in NamesArray[i].)
{
NamesArray2[idx++] = k.value.ToString();
}
}
Why don't you try doing:
myclass[] arr = data.ToArray();
Edit:
To return the array so it's visible from VBA, you'd need to have your class as ComVisible.
[ComVisible(true)]
public class main
{
public list<myclass> data { get; set; }
}
[ComVisible(true)]
public class myclass
{
public string variety { get; set; }
public string ordertype { get; set; }
public string producttype { get; set; }
}
[ComVisible(true)]
public myclass[] myclasses()
{
myclass[] arr = data.ToArray();
return arr;
}
#freeflow has a great reference link that you can use: https://analystcave.com/excel-use-c-sharp-in-excel-vba/

working with DataTabe, List<> and DataGridView inside nested For Next

Im trying to get information out of certain List inside For Next loop to be able to place the data in a DataTable so I can show it in a DataGridView. Well I have been searching and trying for hours but I dont gett the result I want. I think I'm almost there but something I'm doing wrong. Is ther eanybody willing to help me?
private void Form4_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
//Set first column names
//dt.Columns.Add("Sample No");
for (int i = 0; i <= frmMain.iAnaChan-1; i++)
//Loop to add analog channel columns
{
dt.Columns.Add(frmMain.AnalogChannelList[i].ch_id.ToString());
}
DataRow row = dt.NewRow();
for (int sam = 1; sam <= frmMain.TotSamples ; sam++)
{
for (int chan = 0; chan <= frmMain.iAnaChan -1; chan++)
{
row[chan] = frmMain.channeldata[sam-1].sSampleVal.ToString();
dt.Rows.Add(row);
}
}
dataGridViewSampleData.DataSource = dt;
}
Class
public class aChannelList
{
//Class for retreiving all Analog Channel information
public string An { get; set; }
public string ch_id { get; set; }
public string ph { get; set; }
public string ccbm { get; set; }
public string uu { get; set; }
public string chanMult { get; set; }
public string chanOffset { get; set; }
public string skew { get; set; }
public string minRange { get; set; }
public string maxRange { get; set; }
public string primVal { get; set; }
public string secVal { get; set; }
public string scalingID { get; set; }
}
public class SampledData
{
//This class retreives the relevant information into a list to give the relevant channel data visible into a datagrid for information
public string sSampleNo { get; set; }
public string sTimeStamp { get; set; }
public string sSampleVal { get; set; }
}
iAnaChan is an integer than should set the amount of "channels" i.e. columns I need. And this works correct if I don't run the below code.
Than I need to start rows, the amount of rows have the values of frmMain.TotSamples and place them inside a a For Next loop so it will place the rows automatically. Than I try to add in the columns the sample values in the repectivly columns and add a row. After all loops have been passed thru I try to place it in a DataTable. But unfortunatly this doesn't work and I really would like to know what I am doing wrong?
You can create public ObservableCollection<object> Items { get; set; } into which you will add the items using a foreach loop
foreach (var item in dataCollection)
Items.Add(item)
Then just set DataGrid's ItemSource to Items. DataGrid is able to autogenerate itself this way.

Retrieve values from JSON

I am retrieving values from JSON and want to compare that. but I am getting Index Out of Range Exception on:
string email = contactdata.data[0].email[i].value;
Code:
int length = contactdata.data.Length;
for (int i = 0; i <= length; i++)
{
string email = contactdata.data[0].email[i].value;
if (contactemail == email)
{
counter++;
flag = 1;
break;
}
}
JSON Class:
public class Rootobject
{
public bool success { get; set; }
public Datum[] data { get; set; }
public Additional_Data additional_data { get; set; }
}
public class Additional_Data
{
public Pagination pagination { get; set; }
}
public class Pagination
{
public int start { get; set; }
public int limit { get; set; }
public bool more_items_in_collection { get; set; }
}
public class Datum
{
public int id { get; set; }
public Email[] email { get; set; }
}
public class Email
{
public string label { get; set; }
public string value { get; set; }
public bool primary { get; set; }
}
change the line
int length = contactdata.data.Length;
to
int length = contactdata.data[0].email.Length;
and change the condition in the for loop from i <= length to i < length.
Change this
for (int i = 0; i <= length; i++)
with
for (int i = 0; i < length; i++)
index start alwais from 0
Your iteration variable is on the contactdata.datanot on email, thus your i variable is on these indexes.
As I mentioned in a comment, using a nested for loop over data and ALSO over email will ensure you actually have an email you can look at!
The index out of range error means that you're trying to access an item in an array that doesn't exist.
I did not test the following code, but I used really explicit variable names in the loop to show you what I'm trying to count, and how I can only access something in an array if I know that it actually exists:
//first get the length of data
var dataLength = contactdata.data.Length;
//now loop through it
for (var dataCounter = 0; dataCounter < dataLength; dataCounter++){
//next get the length of email - is there even an email available?
var emailLength = contactdata.data[dataCounter].email.Length;
for (var emailCounter = 0; emailCounter < emailLength; emailCounter ++){
//now you can access the email and work with it.
if (contactemail == contactdata.data[dataCounter].email[emailCounter]){
// here do your code
}
}
}

Update List<T> through self join?

First off I am very new to LINQ.
I have a list which has data something like this :
list
list[0] = id=1,block=10,sg=320,dc=null
list[1] = id=1,block=10,sg=null,dc=320
list[2] = id=2,block=15,sg=400,dc=null
list[3] = id=2,block=15,sg=null,dc=400
I want to update this list such that :
if(sg where block=x and id=y is null)
then set sg = (sg where block=x and id=y is not null)
and similarly for dc
Desired Result:
list[0] = id=1,block=10,sg=320,dc=320
list[1] = id=2,block=15,sg=400,dc=400
NOTE: id and block are identifying factors here.
CLASS:
public class dcsg
{
public long id { get; set; }
public Nullable<decimal> dcvalue { get; set; }
public Nullable<decimal> sgvalue { get; set; }
public Nullable<int> revision { get; set; }
public Nullable<long> timestampid { get; set; }
public decimal fuelcost { get; set; }
public Nullable<short> isdeleted { get; set; }
public Nullable<long> blockno { get; set; }
public int stageid { get; set; }
}
You could achieve this using Linq, GroupBy.
lists = lists.GroupBy(x=> new {x.id, x.blockno})
.Select(x=>
{
var sg1 = x.FirstOrDefault(f=>f.sgvalue.HasValue);
var dc1 = x.FirstOrDefault(f=>f.dcvalue.HasValue);
return new dcsg() // create class instance if have one.
{
id= x.Key.id,
blockno= x.Key.blockno,
sgvalue = sg1==null? null; sg1.sgvalue,
dcvalue = dc1==null? null; dc1.dcvalue,
// copy other properties (if needed).
};
})
.ToList();
Obviously, code snippet written with two assumptions.
In case of multiple sg appear for same block first sg will betaken (but this can be changed based on need).
Based on your example, id,block are used to group list items.

Categories