I've been trying to add to a list of lists adding information from an sql db. The error I get when adding new info to a list is this:
"An exception of type 'System.NullReferenceException' occurred in StatusScope.dll but was not handled in user code
Additional information: Object reference not set to an instance of an object."
How would I solve this error?
MapLogic.cs
public static List<MapModel.ClientInfo> GetClientsData()
{
SqlConnection Connection = site.Models.Shared.DBConnection.GetConnection();
SqlDataReader Reader = null;
SqlCommand Command = new SqlCommand("SELECT DocInfo.DocID, DocInfo.DocName, DocInfo.DocPic, DocInfo.PatientAcceptance, ClientInfo.ClientName, ClientInfo.AddressLocal, ClientInfo.AddressBroad, ClientInfo.Phone, ClientInfo.Lat, ClientInfo.Long, ClientInfo.ClientID FROM DocInfo INNER JOIN ClientInfo ON DocInfo.ClientID = ClientInfo.ClientID;", Connection);
Reader = Command.ExecuteReader();
var ClientsData = new List<MapModel.ClientInfo> { };
int IDCounter = 0;
bool FirstRun = false;
while (Reader.Read())
{
if (!FirstRun)
{
ClientsData.Add(new MapModel.ClientInfo { Id = IDCounter, ClientID = Reader["ClientID"].ToString(), ClientName = Reader["ClientName"].ToString(), DocPic = Reader["DocPic"].ToString(), PatientAcceptance = Reader["PatientAcceptance"].ToString(), AddressLocal = Reader["AddressLocal"].ToString(), AddressBroad = Reader["AddressLocal"].ToString(), Phone = Reader["Phone"].ToString(), latitude = Reader["Lat"].ToString(), longitude = Reader["Long"].ToString(), DocNames = { } });
FirstRun = true;
}
else
{
for (var x = 0; x < ClientsData.Count; x++)
{
if (ClientsData[x].ClientID == Reader["ClientID"].ToString())
{
ClientsData[x].DocNames.Add("123"); //error occurs here
}
else
{
ClientsData.Add(new MapModel.ClientInfo { Id = IDCounter, ClientID = Reader["ClientID"].ToString(), ClientName = Reader["ClientName"].ToString(), DocPic = Reader["DocPic"].ToString(), PatientAcceptance = Reader["PatientAcceptance"].ToString(), AddressLocal = Reader["AddressLocal"].ToString(), AddressBroad = Reader["AddressLocal"].ToString(), Phone = Reader["Phone"].ToString(), latitude = Reader["Lat"].ToString(), longitude = Reader["Long"].ToString() });
}
}
}
IDCounter++;
}
Connection.Close();
return ClientsData;
}
MapModel.cs
public class ClientInfo
{
public int Id { get; set; }
public string ClientID { get; set; }
public string ClientName { get; set; }
public List<string> DocNames { get; set; }
public string DocPic { get; set; }
public string PatientAcceptance { get; set; }
public string AddressLocal { get; set; }
public string AddressBroad { get; set; }
public string Phone { get; set; }
public string latitude { get; set; }
public string longitude { get; set; }
}
Do you ever set DocNames to anything? If not, it will be null.
In the constructor for ClientInfo you should have
DocNames = new List<string>();
to initialize an empty list.
Isn't it the case of testing whether ClientsData[x].DocNames is null before adding? You could change your code to
if(ClientsData[x].DocNames == null) {
ClientsData[x].DocNames = new List<string>();
}
ClientsData[x].DocNames.Add("123");
so that it always works.
In both lines where you add a new MapModel.ClientInfo to your ClientsData list, you need to initialize DocNames to a new List() otherwise whenever you try to access DocNames, it's always null. So, in both places you need to do the following:
ClientsData.Add(new MapModel.ClientInfo
{
Id = IDCounter,
//.
//. removing code just to make my answer shorter
//.
DocNames = new List<string>()
});
Related
I am new to web api and C#. I am creating a function where I am calling values from table which has 33 rows. the query is this:
Select * from T_SVRS_Reg_Trans
I have created a model where I have put out properties like so:
public class UserModel
{
public int ID { get; set; }
public string OrgUnit { get; set; }
public string TDC { get; set; }
public string CustCode { get; set; }
public string CustName { get; set; }
public string DestCode { get; set; }
public string EMV { get; set; }
public string Service { get; set; }
public string SPCCode { get; set; }
public string SPCode { get; set; }
public string Remarks { get; set; }
public int Stage { get; set; }
public string Cost { get; set; }
public string SAPUpdate { get; set; }
public string Active { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public string UpdatedBy { get; set; }
public DateTime UpdatedOn { get; set; }
}
Now I am calling the table values to get added in these properties. My function for that is this:
[HttpPost]
[Route("GetTableValue")]
public IHttpActionResult GetTableValue()
{
try
{
UserModel objUserModel = new UserModel();
ManageUserData ObjManageUserData = new ManageUserData();
var sqlDataTable = ObjManageUserData.GetTableValue();
if (sqlDataTable.Rows.Count > 0)
{
for (int i = 0; (i < sqlDataTable.Rows.Count); i++)
{
objUserModel.OrgUnit=(sqlDataTable.Rows[i]["TRT_Org_ID"].ToString());
objUserModel.TDC = (sqlDataTable.Rows[i]["TRT_TDC_Code"].ToString());
objUserModel.CustCode = (sqlDataTable.Rows[i]["TRT_Cust_Code"].ToString());
objUserModel.CustName = (sqlDataTable.Rows[i]["TRT_Cust_Name"].ToString());
objUserModel.DestCode = (sqlDataTable.Rows[i]["TRT_Dest_Code"].ToString());
objUserModel.EMV = (sqlDataTable.Rows[i]["TRT_EMV"].ToString());
objUserModel.Service = (sqlDataTable.Rows[i]["TRT_Service"].ToString());
objUserModel.SPCCode = (sqlDataTable.Rows[i]["TRT_SPC_Code"].ToString());
objUserModel.SPCode = (sqlDataTable.Rows[i]["TRT_SP_Code"].ToString());
objUserModel.Remarks = (sqlDataTable.Rows[i]["TRT_Remarks"].ToString());
objUserModel.Stage = (int)(sqlDataTable.Rows[i]["TRT_Stage"]);
objUserModel.Cost = (sqlDataTable.Rows[i]["TRT_Cost_Imp"].ToString());
objUserModel.SAPUpdate = (sqlDataTable.Rows[i]["TRT_SAP_Update_Status"].ToString());
objUserModel.Active = (sqlDataTable.Rows[i]["TRT_IS_ACTIVE"].ToString());
objUserModel.CreatedBy = (sqlDataTable.Rows[i]["TRT_CREATED_BY"].ToString());
objUserModel.CreatedOn = (DateTime)(sqlDataTable.Rows[i]["TRT_CREATED_ON"]);
objUserModel.UpdatedBy = (sqlDataTable.Rows[i]["TRT_UPDATED_BY"].ToString());
objUserModel.UpdatedOn = (DateTime)(sqlDataTable.Rows[i]["TRT_UPDATED_ON"]);
}
}
return Ok(objUserModel);
}
catch (Exception ex)
{
return Content(HttpStatusCode.NoContent, "Something went wrong");
}
However I am noticing that only the last table value is added to the model and the rest of it is not. I want to add all 33 values in model form to the model mentioned. Is there any way to do this?
PLease help
}
You overwrite objUserModel each iteration. Create a new one inside the loop, add them to a List<UserModel>, returning that to your view.
Also consider dropping the archaic Hungarian notation (the "obj" prefix). Also consider using an ORM instead of mapping columns to properties using strings.
You should create a List or Array of type UserModel and adding items into it
try
{
List<UserModel> result = new List<UserModel>();
ManageUserData ObjManageUserData = new ManageUserData();
var sqlDataTable = ObjManageUserData.GetTableValue();
if (sqlDataTable.Rows.Count > 0)
{
for (int i = 0; (i < sqlDataTable.Rows.Count); i++)
{
UserModel objUserModel = new UserModel();
objUserModel.OrgUnit = (sqlDataTable.Rows[i]["TRT_Org_ID"].ToString());
objUserModel.TDC = (sqlDataTable.Rows[i]["TRT_TDC_Code"].ToString());
objUserModel.CustCode = (sqlDataTable.Rows[i]["TRT_Cust_Code"].ToString());
objUserModel.CustName = (sqlDataTable.Rows[i]["TRT_Cust_Name"].ToString());
objUserModel.DestCode = (sqlDataTable.Rows[i]["TRT_Dest_Code"].ToString());
objUserModel.EMV = (sqlDataTable.Rows[i]["TRT_EMV"].ToString());
objUserModel.Service = (sqlDataTable.Rows[i]["TRT_Service"].ToString());
objUserModel.SPCCode = (sqlDataTable.Rows[i]["TRT_SPC_Code"].ToString());
objUserModel.SPCode = (sqlDataTable.Rows[i]["TRT_SP_Code"].ToString());
objUserModel.Remarks = (sqlDataTable.Rows[i]["TRT_Remarks"].ToString());
objUserModel.Stage = (int)(sqlDataTable.Rows[i]["TRT_Stage"]);
objUserModel.Cost = (sqlDataTable.Rows[i]["TRT_Cost_Imp"].ToString());
objUserModel.SAPUpdate = (sqlDataTable.Rows[i]["TRT_SAP_Update_Status"].ToString());
objUserModel.Active = (sqlDataTable.Rows[i]["TRT_IS_ACTIVE"].ToString());
objUserModel.CreatedBy = (sqlDataTable.Rows[i]["TRT_CREATED_BY"].ToString());
objUserModel.CreatedOn = (DateTime)(sqlDataTable.Rows[i]["TRT_CREATED_ON"]);
objUserModel.UpdatedBy = (sqlDataTable.Rows[i]["TRT_UPDATED_BY"].ToString());
objUserModel.UpdatedOn = (DateTime)(sqlDataTable.Rows[i]["TRT_UPDATED_ON"]);
result.Add(objUserModel);
}
}
return Ok(result);
}
catch (Exception ex)
{
return Content(HttpStatusCode.NoContent, "Something went wrong");
}
You need to use the collection instead of single object UserModel.
[HttpPost]
[Route("GetTableValue")]
public IHttpActionResult GetTableValue()
{
try
{
ManageUserData ObjManageUserData = new ManageUserData();
var sqlDataTable = ObjManageUserData.GetTableValue();
List<UserModel> userModels = new List<UserModel>();
if (sqlDataTable.Rows.Count > 0)
{
for (int i = 0; (i < sqlDataTable.Rows.Count); i++)
{
var objUserModel = new UserModel()
objUserModel.OrgUnit = (sqlDataTable.Rows[i]["TRT_Org_ID"].ToString());
objUserModel.TDC = (sqlDataTable.Rows[i]["TRT_TDC_Code"].ToString());
objUserModel.CustCode = (sqlDataTable.Rows[i]["TRT_Cust_Code"].ToString());
objUserModel.CustName = (sqlDataTable.Rows[i]["TRT_Cust_Name"].ToString());
objUserModel.DestCode = (sqlDataTable.Rows[i]["TRT_Dest_Code"].ToString());
objUserModel.EMV = (sqlDataTable.Rows[i]["TRT_EMV"].ToString());
objUserModel.Service = (sqlDataTable.Rows[i]["TRT_Service"].ToString());
objUserModel.SPCCode = (sqlDataTable.Rows[i]["TRT_SPC_Code"].ToString());
objUserModel.SPCode = (sqlDataTable.Rows[i]["TRT_SP_Code"].ToString());
objUserModel.Remarks = (sqlDataTable.Rows[i]["TRT_Remarks"].ToString());
objUserModel.Stage = (int)(sqlDataTable.Rows[i]["TRT_Stage"]);
objUserModel.Cost = (sqlDataTable.Rows[i]["TRT_Cost_Imp"].ToString());
objUserModel.SAPUpdate = (sqlDataTable.Rows[i]["TRT_SAP_Update_Status"].ToString());
objUserModel.Active = (sqlDataTable.Rows[i]["TRT_IS_ACTIVE"].ToString());
objUserModel.CreatedBy = (sqlDataTable.Rows[i]["TRT_CREATED_BY"].ToString());
objUserModel.CreatedOn = (DateTime)(sqlDataTable.Rows[i]["TRT_CREATED_ON"]);
objUserModel.UpdatedBy = (sqlDataTable.Rows[i]["TRT_UPDATED_BY"].ToString());
objUserModel.UpdatedOn = (DateTime)(sqlDataTable.Rows[i]["TRT_UPDATED_ON"]);
userModels.Add(userModels);
}
}
return Ok(userModels);
}
catch (Exception ex)
{
return Content(HttpStatusCode.NoContent, "Something went wrong");
}
}
As you are expecting more than one row to be returned, you need to collect the rows as you iterate your result set into some sort of collection/list/array.
Try making a list of your UserModel
List<UserModel> objUserModels = new List<UserModel>();
And then adding each object to the list after each iteration of your for loop:
for (int i = 0; (i < sqlDataTable.Rows.Count); i++)
{
var objUserModel = new UserModel();
objUserModel.OrgUnit=(sqlDataTable.Rows[i]["TRT_Org_ID"].ToString());
objUserModel.TDC = (sqlDataTable.Rows[i]["TRT_TDC_Code"].ToString());
objUserModel.CustCode = (sqlDataTable.Rows[i]["TRT_Cust_Code"].ToString());
objUserModel.CustName = (sqlDataTable.Rows[i]["TRT_Cust_Name"].ToString());
objUserModel.DestCode = (sqlDataTable.Rows[i]["TRT_Dest_Code"].ToString());
objUserModel.EMV = (sqlDataTable.Rows[i]["TRT_EMV"].ToString());
objUserModel.Service = (sqlDataTable.Rows[i]["TRT_Service"].ToString());
objUserModel.SPCCode = (sqlDataTable.Rows[i]["TRT_SPC_Code"].ToString());
objUserModel.SPCode = (sqlDataTable.Rows[i]["TRT_SP_Code"].ToString());
objUserModel.Remarks = (sqlDataTable.Rows[i]["TRT_Remarks"].ToString());
objUserModel.Stage = (int)(sqlDataTable.Rows[i]["TRT_Stage"]);
objUserModel.Cost = (sqlDataTable.Rows[i]["TRT_Cost_Imp"].ToString());
objUserModel.SAPUpdate = (sqlDataTable.Rows[i]["TRT_SAP_Update_Status"].ToString());
objUserModel.Active = (sqlDataTable.Rows[i]["TRT_IS_ACTIVE"].ToString());
objUserModel.CreatedBy = (sqlDataTable.Rows[i]["TRT_CREATED_BY"].ToString());
objUserModel.CreatedOn = (DateTime)(sqlDataTable.Rows[i]["TRT_CREATED_ON"]);
objUserModel.UpdatedBy = (sqlDataTable.Rows[i]["TRT_UPDATED_BY"].ToString());
objUserModel.UpdatedOn = (DateTime)(sqlDataTable.Rows[i]["TRT_UPDATED_ON"]);
objUserModels.Add(objUserModel);
}
And then return your list of objects:
return Ok(objUserModels);
I have a C# project and looking for simple solution for map one class object data to list of another class object.
This is my input class
public class RatesInput
{
public string Type1 { get; set; }
public string Break1 { get; set; }
public string Basic1 { get; set; }
public string Rate1 { get; set; }
public string Type2 { get; set; }
public string Break2 { get; set; }
public string Basic2 { get; set; }
public string Rate2 { get; set; }
public string Type3 { get; set; }
public string Break3 { get; set; }
public string Basic3 { get; set; }
public string Rate3 { get; set; }
}
This is my another class structure
public class RateDetail
{
public string RateType { get; set; }
public decimal Break { get; set; }
public decimal Basic { get; set; }
public decimal Rate { get; set; }
}
it has a object like below. (For easiering the understanding, I use hardcoded values and actually values assign from a csv file)
RatesInput objInput = new RatesInput();
objInput.Type1 = "T";
objInput.Break1 = 100;
objInput.Basic1 = 50;
objInput.Rate1 = 0.08;
objInput.Type2 = "T";
objInput.Break2 = 200;
objInput.Basic2 = 50;
objInput.Rate2 = 0.07;
objInput.Type3 = "T";
objInput.Break3 = 500;
objInput.Basic3 = 50;
objInput.Rate3 = 0.06;
Then I need to assign values to "RateDetail" list object like below.
List<RateDetail> lstDetails = new List<RateDetail>();
//START Looping using foreach or any looping mechanism
RateDetail obj = new RateDetail();
obj.RateType = //first iteration this should be assigned objInput.Type1, 2nd iteration objInput.Type2 etc....
obj.Break = //first iteration this should be assigned objInput.Break1 , 2nd iteration objInput.Break2 etc....
obj.Basic = //first iteration this should be assigned objInput.Basic1 , 2nd iteration objInput.Basic2 etc....
obj.Rate = //first iteration this should be assigned objInput.Rate1, 2nd iteration objInput.Rate2 etc....
lstDetails.Add(obj); //Add obj to the list
//END looping
Is there any way to convert "RatesInput" class data to "RateDetail" class like above method in C#? If yes, how to iterate data set?
Try this:
public class RatesList : IEnumerable<RateDetail>
{
public RatesList(IEnumerable<RatesInput> ratesInputList)
{
RatesInputList = ratesInputList;
}
private readonly IEnumerable<RatesInput> RatesInputList;
public IEnumerator<RateDetail> GetEnumerator()
{
foreach (var ratesInput in RatesInputList)
{
yield return new RateDetail
{
RateType = ratesInput.Type1,
Break = Convert.ToDecimal(ratesInput.Break1, new CultureInfo("en-US")),
Basic = Convert.ToDecimal(ratesInput.Basic1, new CultureInfo("en-US")),
Rate = Convert.ToDecimal(ratesInput.Rate1, new CultureInfo("en-US"))
};
yield return new RateDetail
{
RateType = ratesInput.Type2,
Break = Convert.ToDecimal(ratesInput.Break2),
Basic = Convert.ToDecimal(ratesInput.Basic2),
Rate = Convert.ToDecimal(ratesInput.Rate2, new CultureInfo("en-US"))
};
yield return new RateDetail
{
RateType = ratesInput.Type3,
Break = Convert.ToDecimal(ratesInput.Break3),
Basic = Convert.ToDecimal(ratesInput.Basic3),
Rate = Convert.ToDecimal(ratesInput.Rate3, new CultureInfo("en-US"))
};
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
And use:
var list = new RatesList(new List<RatesInput>() { objInput });
foreach (var item in list)
{
Console.WriteLine(item.Basic);
}
You can use Reflection to get the properties info like this:
var props = objInput.GetType().GetProperties();
var types = props.Where(x => x.Name.StartsWith("Type"))
.Select(x => x.GetValue(objInput)).ToList();
var breaks = props.Where(x => x.Name.StartsWith("Break"))
.Select(x => x.GetValue(objInput)).ToList();
var basics = props.Where(x => x.Name.StartsWith("Basic"))
.Select(x => x.GetValue(objInput)).ToList();
var rates = props.Where(x => x.Name.StartsWith("Rate"))
.Select(x => x.GetValue(objInput)).ToList();
List<RateDetail> lstDetails = new List<RateDetail>();
for (int i = 0; i < types.Count; i++)
{
lstDetails.Add(new RateDetail
{
RateType = types[i].ToString(),
Break = Convert.ToDecimal(breaks[i]),
Basic = Convert.ToDecimal(basics[i]),
Rate = Convert.ToDecimal(rates[i])
});
}
I have a block of code that preps a query here:
var AssetTagParam = new SQLiteParameter("#AssetTagParam", SqlDbType.Int) { Value = item.AssetTag };
var VendorParam = new SQLiteParameter("#VendorParam", SqlDbType.Text) { Value = item.Vendor };
var DeviceParam = new SQLiteParameter("#DeviceParam", SqlDbType.Text) { Value = item.Device };
var AttributeParam = new SQLiteParameter("#AttributeParam", SqlDbType.Text) { Value = item.Attribute };
var DeviceTypeParam = new SQLiteParameter("#DeviceTypeParam", SqlDbType.Text) { Value = item.DeviceType };
var SystemParam = new SQLiteParameter("#SystemParam", SqlDbType.Text) { Value = item.System };
var LocationParam = new SQLiteParameter("#LocationParam", SqlDbType.Text) { Value = item.Location };
var OnLoanParam = new SQLiteParameter("#OnLoanParam", SqlDbType.Binary) { Value = item.OnLoan };
var NotesParam = new SQLiteParameter("#NotesParam", SqlDbType.Text) { Value = item.Notes };
var LastModifiedTimeParam = new SQLiteParameter("#LastModifiedTimeParam", SqlDbType.Text) { Value = item.LastModifiedTime };
var LastModifiedPersonParam = new SQLiteParameter("#LastModifiedPersonParam", SqlDbType.Text) { Value = item.LastModifiedPerson };
var IsDeletedParam = new SQLiteParameter("#IsDeletedParam", SqlDbType.Binary) { Value = item.IsDeleted };
SQLiteCommand insertSQL = new SQLiteCommand("INSERT INTO Inventory(AssetTag, Vendor, Device, Attribute, DeviceType, System, Notes, OnLoan, Location)" +
" VALUES (#AssetTagParam, #VendorParam, #DeviceParam, #AttributeParam, #DeviceTypeParam, #SystemParam, #NotesParam, #OnLoanParam, #LocationParam)", conn);
insertSQL.Parameters.Add(AssetTagParam);
insertSQL.Parameters.Add(VendorParam);
insertSQL.Parameters.Add(DeviceParam);
insertSQL.Parameters.Add(AttributeParam);
insertSQL.Parameters.Add(DeviceTypeParam);
insertSQL.Parameters.Add(SystemParam);
insertSQL.Parameters.Add(LocationParam);
insertSQL.Parameters.Add(OnLoanParam);
insertSQL.Parameters.Add(NotesParam);
insertSQL.Parameters.Add(LastModifiedTimeParam);
insertSQL.Parameters.Add(LastModifiedPersonParam);
insertSQL.Parameters.Add(IsDeletedParam);
For Reference, the Item class looks like this:
public class Item
{
public int AssetID { get; set; }
public int AssetTag { get; set; }
public string Vendor { get; set; }
public string Device { get; set; }
public string Attribute { get; set; }
public string DeviceType { get; set; }
public string System { get; set; }
public string Location { get; set; }
public bool OnLoan { get; set; }
public string Notes { get; set; }
public string LastModifiedTime { get; set; }
public string LastModifiedPerson { get; set; }
public bool IsDeleted { get; set; }
}
When I run this code, I will always run into the generic error:
Input string was not in a correct format.
After trying to figure out the source of this issue, assuming that I typed something wrong in the process, I ran into the issue that all my Param vars had their dbType set to Int32. I thought I was setting with the parameter SqlDbType.Text, but I must be misunderstanding this?
How do I set the dbtype of my inputs to Text instead of Int32?
The mistake I was making is using SqlDbType to define the type of data. I should have been using System.Data.DbType to define the data, so this:
var VendorParam = new SQLiteParameter("#VendorParam", SqlDbType.Text) { Value = item.Vendor };
Should instead be changed to this:
var VendorParam = new SQLiteParameter("#VendorParam", System.Data.DbType.String) { Value = item.Vendor };
public class kingdomAddModel
{
public string title { get; set; }
public string details { get; set; }
//public HttpPostedFileBase fileUpload { get; set; }
//public string retrieveFile { get; set; }
public FileAttr files { get; set; }
}
public class FileAttr
{
public HttpPostedFileBase fileUpload { get; set; }
public string retrieveFile { get; set; }
}
var getDailyDevotions = db.DailyDevotions.Select(d => new { title = d.DevotionsTitle, details = d.DevotionsDetails, retriveFileAudio = d.VoiceNotes });
List<kingdomAddModel> listdevotions = new List<kingdomAddModel>();
foreach (var getDevotions in getDailyDevotions)
{
kingdomlist = new kingdomAddModel();
kingdomlist.title = getDevotions.title;
kingdomlist.details = getDevotions.details;
fileattr = new FileAttr();
fileattr.retrieveFile = getDevotions.retriveFileAudio;
kingdomlist.files.retrieveFile = fileattr.retrieveFile; //erros appears here!
}
The line line kingdomlist.files.retrieveFile throws the exception, tried googling but I dont get simular problem. I just want to assign the value and will pull on my view.
Do not access properties of FileAttr directly, only use files with the instance of kingdomAddModel. Don't mixup them
Replace
foreach (var getDevotions in getDailyDevotions)
{
kingdomlist = new kingdomAddModel();
kingdomlist.title = getDevotions.title;
kingdomlist.details = getDevotions.details;
fileattr = new FileAttr();
fileattr.retrieveFile = getDevotions.retriveFileAudio;
kingdomlist.files.retrieveFile = fileattr.retrieveFile; //erros appears here!
}
with
foreach (var getDevotions in getDailyDevotions)
{
kingdomlist = new kingdomAddModel
{
title = getDevotions.title,
details = getDevotions.details,
files = new FileAttr
{
retrieveFile = getDevotions.retriveFileAudio,
//fileUpload = some value here
}
};
listdevotions.Add(kingdomlist);
}
OR use Linq
listdevotions = (from getDevotions in getDailyDevotions
select new kingdomAddModel
{
title = getDevotions.title,
details = getDevotions.details,
files = new FileAttr
{
retrieveFile = getDevotions.retriveFileAudio,
//fileUpload = some value here
}
}).ToList();
I'm currently working on parsing a csv file that was exported by another application. This application exported the data in a strange way. This export is from accoutning and it looks similar to this..
I'm trying to figure out a way to read the csv file, then split up the multiple 'All Accounts' values and 'Amt' Values so that M200 and 300.89 is another entry, M300 and 400.54 are another entry, and M400 and 100.00 are another entry. So after inserting this single row into the database, I should actually have 4 rows like so..
This is how I'm currently reading and inserting into the database.
List<RawData> data = new List<RawData>();
try
{
string text = File.ReadAllText(lblFileName.Text);
string[] lines = text.Split('\n');
int total = 0, reduced = 0;
foreach (string line in lines)
{
RawData temp = new RawData(line);
total++;
if (!(temp.FirstAccount.Length == 0 || temp.FirstAccount == "1ST-ACCT-NO"))
{
reduced++;
data.Add(temp);
}
}
}
catch (IOException ex)
{
Console.WriteLine("Unable to read file. " + ex.ToString());
MessageBox.Show(ex.ToString());
}
try
{
foreach (RawData rData in data)
{
tCarsInTransit cit = new tCarsInTransit
{
FIRST_ACCT_NO = rData.FirstAccount,
ACCOUNT_NO_DV = rData.AccountNoDv,
ACCT_NO = rData.AcctNo,
ACCT_NO_L = rData.AccNoL,
ACCT_NUM_DV = rData.AcctNumDv,
ACCT_PFX = rData.AcctPfx,
ACCT_PFX_PRT = rData.AcctPfxPrt,
ACCT_TYPE_DV = rData.AcctTypeDv,
ADV_NO = rData.AdvNo,
ALL_PRT_FLAG = rData.AllPrtFlag,
AMT = rData.Amt,
AMT_GLE = rData.AmtGle,
BASE_GLE = rData.BaseGle,
CNT_CAT = rData.CntCat,
COLD_PRT_FLAG = rData.ColdPrtFlag,
COST_DV = rData.CostDv,
COST_OVRD_FLAG_DV = rData.CostOvrdFlagDv,
CR_ACCT_DV = rData.CrAcctDv,
CR_ACCT_DV_GLE = rData.CrAcctDvGle,
CROSS_POSTING_FLAG = rData.CrossPostingFlag,
CROSS_POST_CAT = rData.CrossPostCat,
CTRL_NO = rData.CtrlNo,
CTRL_TYPE_DV = rData.CtrlTypeDv,
DESC_REQD_DV = rData.DescReqdDv,
DR_ACCT_DV = rData.DrAcctDv,
GL_DIST_ACCT_DV = rData.GLDistAcctDv,
GL_DIST_DV = rData.GLDistDv,
GRP_NO_DV = rData.GrpNoDv,
ID_PORT_DATE_TIME_FMT_CAT = rData.IdPortDateTimeFmtCat,
INACTIVITY_DV = rData.InactivityDv,
JOIN_COL = rData.JoinCol,
JRNL_DATE = rData.JrnlDate,
JRNL_PFX = rData.JrnlPfx
};
tCIT.tCarsInTransits.Add(cit);
tCIT.SaveChanges();
lblMessage.ForeColor = System.Drawing.Color.Green;
lblMessage.Text = "Finished uploading. ";
}
}
catch (DbEntityValidationException ex)
{
foreach (var eve in ex.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
I am not sure how to accomplish this. The above currently inserts the csv file into Sql Server the exact way the csv file was exported. Any ideas would greatly be appreciated! Thanks!
EDIT: Here is the RawData class.
class RawData
{
public string FirstAccount { get; set; }
public string AccountNoDv { get; set; }
public string AcctNo { get; set; }
public string AccNoL { get; set; }
public string AcctNumDv { get; set; }
public string AcctPfx { get; set; }
public string AcctPfxPrt { get; set; }
public string AcctTypeDv { get; set; }
public string AdvNo { get; set; }
public string AllPrtFlag { get; set; }
public string Amt { get; set; }
public string AmtGle { get; set; }
public string BaseGle { get; set; }
public string CntCat { get; set; }
public string ColdPrtFlag { get; set; }
public string CostDv { get; set; }
public string CostOvrdFlagDv { get; set; }
public string CrAcctDv { get; set; }
public string CrAcctDvGle { get; set; }
public string CrossPostingFlag { get; set; }
public string CrossPostCat { get; set; }
public string CtrlNo { get; set; }
public string CtrlTypeDv { get; set; }
public string DescReqdDv { get; set; }
public string DrAcctDv { get; set; }
public string GLDistAcctDv { get; set; }
public string GLDistDv { get; set; }
public string GrpNoDv { get; set; }
public string IdPortDateTimeFmtCat { get; set; }
public string InactivityDv { get; set; }
public string JoinCol { get; set; }
public string JrnlDate { get; set; }
public string JrnlPfx { get; set; }
public RawData(string csvString)
{
string[] citData = csvString.Replace(", ", "").Replace(".,", ".").Split(',');
try
{
FirstAccount = citData[0];
AccountNoDv = citData[1];
AcctNo = citData[2];
AccNoL = citData[3];
AcctNumDv = citData[4];
AcctPfx = citData[5];
AcctPfxPrt = citData[6];
AcctTypeDv = citData[7];
AdvNo = citData[8];
AllPrtFlag = citData[9];
Amt = citData[10];
AmtGle = citData[11];
BaseGle = citData[12];
CntCat = citData[13];
ColdPrtFlag = citData[14];
CostDv = citData[15];
CostOvrdFlagDv = citData[16];
CrAcctDv = citData[17];
CrAcctDvGle = citData[18];
CrossPostingFlag = citData[19];
CrossPostCat = citData[20];
CtrlNo = citData[21];
CtrlTypeDv = citData[22];
DescReqdDv = citData[23];
DrAcctDv = citData[24];
GLDistAcctDv = citData[25];
GLDistDv = citData[26];
GrpNoDv = citData[27];
IdPortDateTimeFmtCat = citData[28];
InactivityDv = citData[29];
JoinCol = citData[30];
JrnlDate = citData[31];
JrnlPfx = citData[32];
}
catch (Exception ex)
{
Console.WriteLine("Something went wrong. " + ex.ToString());
}
}
}
EDIT 2: AllAccounts in the images is acutally 'AccountNoDv' and there are actually many different fields that have multiples like 'AccountNoDv'(AllAccounts) but we might be removing those as this is not a final export. As of right now the two fields I'm worried most about are AccountNoDv and Amt.
Try something like this:
foreach (string line in lines)
{
RawData temp = new RawData(line);
var AllAccounts = temp.AccountNoDv.split(' ');
var Amts = temp.Amt.split(' ');
if (AllAccounts.Length() == Amts.Length() && Amts.Length() > 1) {
// We have multiple values!
reduced++;
for (int i = 0; i < AllAccounts.Length(); i++) {
RawData temp2 = RawDataCopy(temp); // Copy the RawData object
temp2.AccountNoDv = AllAccounts[i];
temp2.Amt = Amts[i];
total++;
data.Add(temp2);
}
}
else {
total++;
if (!(temp.FirstAccount.Length == 0 || temp.FirstAccount == "1ST-ACCT-NO"))
{
reduced++;
data.Add(temp);
}
}
}
And:
private RawData RawDataCopy(RawData copyfrom) {
// Write a function here that returns an exact copy from the one provided
// You might have to create a parameterless constructor for RawData
RawData RawDataCopy = new RawData();
RawDataCopy.FirstAccount = copyfrom.FirstAccount;
RawDataCopy.AccountNoDv = copyfrom.AccountNoDv;
RawDataCopy.AcctNo = copyfrom.AcctNo;
// . . . . . . . .
RawDataCopy.JrnlPfx = copyfrom.JrnlPfx;
return RawDataCopy;
}
Then also add a parameterless constructor to your RawData class:
public RawData()
{
}
Perhaps it would be sexier to implement the ICloneable interface and call the Clone() function instead of the RawDataCopy function, but it gets the idea across.
In Linq you can use SelectMany to increase the number of elements in a list. Here is a rough example of how this could be done. I make the assumption that the number of sub elements in AllAccounts and Amt is the same. A more robust solution would check for these issues.
So after you have loaded your data list:
var expandedData =
data.SelectMany(item =>
// split amount (will just return one item if no spaces)
item.Amt.Split(" ".ToCharArray())
// join this to the split of all accounts
.Zip(item.AllAccounts.Split(" ".ToCharArray()),
// return the joined item as a new anon object
(a,b) => new { amt=a, all=b }),
// take the original list item and the anon object and return our new item
(full,pair) => { full.Amt = pair.amt; full.AllAccounts = pair.all; return full; }));
You will now have a list of your data items with the multiple items expanded into the list.
I don't have test data to test so I might have some minor typos -- but I put in lots of comments to make the Linq as clear as possible.
Here is is simple example I wrote in LinqPad for myself to make sure I understood how SelectMany worked:
string [] list = { "a b c d","e","f g" };
var result = list.SelectMany((e) =>
e.Split(" ".ToCharArray()),
(o,item) => new { org = o, item = item}).Dump();