CSVHelper - ignore blank cells in a row unless they are populated - c#

Using CsvHelper with .NET Core 2.2.
We're parsing a CSV file to then export to a SQL table. There are two different mappings of the CSV columns to the SQL columns, which depend on the first value of each row of the CSV.
This is what we have:
public List<TaskProdEntity> ParseCSVFile()
{
using (var reader = new StreamReader(#"C:\Users\me\Desktop\pfile.csv"))
using (var csv = new CsvReader(reader))
{
csv.Configuration.PrepareHeaderForMatch = (string header, int index) =>
header.Replace(" ", "_").Replace("(", "").Replace(")", "").Replace(".", "");
List<TaskProdEntity> records = new List<TaskProdEntity>();
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
if (csv.GetField<int>(0) == 1)
{
var record = new TaskProdEntity
{
Identifier = "ID Number:" + " " + csv.GetField<string>("Id"),
Region = "Business Mailing Address:" + " " + csv.GetField<string>("Provider_First_Line_Business_Mailing_Address") + " " + csv.GetField<string>("Provider_Second_Line_Business_Mailing_Address") + " " + csv.GetField<string>("Provider_Business_Mailing_Address_City_Name") + " " + csv.GetField<string>("Provider_Business_Mailing_Address_State_Name") + " " + csv.GetField<string>("Provider_Business_Mailing_Address_Postal_Code") + " " + csv.GetField<string>("Provider_Business_Mailing_Address_Country_Code_If_outside_US") + " | " + "Business Practice Location:" + " " + csv.GetField<string>("Provider_First_Line_Business_Practice_Location_Address") + " " + csv.GetField<string>("Provider_Second_Line_Business_Practice_Location_Address") + " " + csv.GetField<string>("Provider_Business_Practice_Location_Address_City_Name") + " " + csv.GetField<string>("Provider_Business_Practice_Location_Address_State_Name") + " " + csv.GetField<string>("Provider_Business_Practice_Location_Address_Postal_Code") + " " + csv.GetField<string>("Provider_Business_Practice_Location_Address_Country_Code_If_outside_US"),
Program = "Taxonomy Group:" + " " + csv.GetField<string>("Taxonomy_Group_1")
};
records.Add(record);
}
else
{
var record = new TaskProdEntity
{
Identifier = "ID Number:" + " " + csv.GetField<string>("Id3"),
Region = "Business Mailing Address:" + " " + csv.GetField<string>("Provider_First_Line_Business_Mailing_Address2") + " " + csv.GetField<string>("Provider_Second_Line_Business_Mailing_Address2") + " " + csv.GetField<string>("Provider_Business_Mailing_Address_City_Name2") + " " + csv.GetField<string>("Provider_Business_Mailing_Address_State_Name2") + " " + csv.GetField<string>("Provider_Business_Mailing_Address_Postal_Code2") + " " + csv.GetField<string>("Provider_Business_Mailing_Address_Country_Code_If_outside_US2") + " | " + "Business Practice Location:" + " " + csv.GetField<string>("Provider_First_Line_Business_Practice_Location_Address2") + " " + csv.GetField<string>("Provider_Second_Line_Business_Practice_Location_Address2") + " " + csv.GetField<string>("Provider_Business_Practice_Location_Address_City_Name2") + " " + csv.GetField<string>("Provider_Business_Practice_Location_Address_State_Name2") + " " + csv.GetField<string>("Provider_Business_Practice_Location_Address_Postal_Code2") + " " + csv.GetField<string>("Provider_Business_Practice_Location_Address_Country_Code_If_outside_US2"),
Program = "Taxonomy Group:" + " " + csv.GetField<string>("Taxonomy_Group_2")
};
records.Add(record);
}
}
return records;
}
}
Because the mapping for the Region field specifically is so messy and long, I really want to extract values from those csv fields only if the field is not blank. In many cases, many of those fields will be blank, and the business does not want a ton of concatenated blanks to end up in the database in these cases.
I am wondering if CsvHelper already has a built-in function to achieve this? If not, how would I implement that logic into the above code?

Since the second TaskProdEntity appears to add a 2 each time to the column header, you could have one method that builds your address.
public List<TaskProdEntity> ParseCSVFile()
{
using (var reader = new StreamReader(#"C:\Users\me\Desktop\pfile.csv"))
using (var csv = new CsvReader(reader))
{
csv.Configuration.PrepareHeaderForMatch = (string header, int index) =>
header.Replace(" ", "_").Replace("(", "").Replace(")", "").Replace(".", "");
List<TaskProdEntity> records = new List<TaskProdEntity>();
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
if (csv.GetField<int>(0) == 1)
{
var record = new TaskProdEntity
{
Identifier = "ID Number:" + " " + csv.GetField<string>("Id"),
Region = GetAddress(csv),
Program = "Taxonomy Group:" + " " + csv.GetField<string>("Taxonomy_Group_1")
};
records.Add(record);
}
else
{
var record = new TaskProdEntity
{
Identifier = "ID Number:" + " " + csv.GetField<string>("Id3"),
Region = GetAddress(csv, "2"),
Program = "Taxonomy Group:" + " " + csv.GetField<string>("Taxonomy_Group_2")
};
records.Add(record);
}
}
return records;
}
}
private string GetAddress(CsvReader csv, string extension = "")
{
var value = new StringBuilder("Business Mailing Address:");
if (csv.GetField<string>("Provider_First_Line_Business_Mailing_Address" + extension) != string.Empty)
{
value.Append(" " + csv.GetField<string>("Provider_First_Line_Business_Mailing_Address" + extension));
}
if (csv.GetField<string>("Provider_Second_Line_Business_Mailing_Address" + extension) != string.Empty)
{
value.Append(" " + csv.GetField<string>("Provider_Second_Line_Business_Mailing_Address" + extension));
}
// The rest of the if statements..............
return value.ToString();
}

Related

Simplify list.add of unknown amount of entries

So I am currently working on a calculator.
One of the requirements is to store the history, which I currently do in a list.
While I have simplified alot of code I can't get my head around simplifying this
if (amountNumbers == 2)
{
memory.Add(userNumbers[0].ToString() + " " + op + " " + userNumbers[1].ToString() + " = " + calculation.ToString());
userNumbers.Clear();
}
if (amountNumbers == 3)
{
memory.Add(userNumbers[0].ToString() + " " + op + " " + userNumbers[1].ToString() + " " + op + " " + userNumbers[2].ToString() + " = " + calculation.ToString());
userNumbers.Clear();
}
if (amountNumbers == 4)
{
memory.Add(userNumbers[0].ToString() + " " + op + " " + userNumbers[1].ToString() + " " + op + " " + userNumbers[2].ToString() + " " + op + " " + userNumbers[3].ToString() + " = " + calculation.ToString());
userNumbers.Clear();
}
if (amountNumbers == 5)
{
memory.Add(userNumbers[0].ToString() + " " + op + " " + userNumbers[1].ToString() + " " + op + " " + userNumbers[2].ToString() + " " + op + " " + userNumbers[3].ToString() + " " + op + " " + userNumbers[4].ToString() + " = " + calculation.ToString());
userNumbers.Clear();
}
Any idea how I simplify this and make the adding dynamic depending on how many values the user has chosen?
Preferably I want to store the whole string within one index since that is how the history is being displayed.
You can just Join userNumbers values with " " + op + " " separator, then concat calculation at end:
string lastExpression = string.Join(" " + op + " ", userNumbers) + // Join values
" = " + calculation.ToString(); // Concat calculation result
memory.Add(lastExpression);
userNumbers.Clear();
There is no matter which amount of values in userNumbers - they all will be joined with " " + op + " " between each other.
Shorter version with string interpolation:
memory.Add($"{string.Join($" {op} ", userNumbers)} = {calculation}");
userNumbers.Clear();
EDIT.
This is very similar idea with #JonasH's answer, just without converting userNumbers to a collection of strings. Join makes it implicitly at behind.
Easy, loop over userNumbers and build your string, then add it to memory once you're done. Like so:
// Ensure that we don't get an 'IndexOutOfBoundsException'
// By clamping 'amountNumbers' to the length if 'userNumbers' if it's larger
if (amountNumbers > userNumbers.Length)
amountNumbers = userNumbers.Length;
// You could use a normal 'string' and '... += ...' but 'StringBuilder' is more efficient
var sb = new StringBuilder();
for (int i = 0; i < amountNumbers; i++)
sb.Append($"{userNumbers[i].ToString()} ");
// Add the calculation, no space at the start required as the loop adds a trailing space
sb.Append($"= {calculation.ToString()}");
memory.Add(sb.ToString());
Use .Take(amountNumbers) to get at most amountNumbers of user numbers, . And String.Join to combine strings with some separator between each:
var users = userNumbers.Take(amountNumbers).Select(s => s.ToString());
var str = string.Join(" " + op + " ", users);
memory.Add(str + " = " + calculation.ToString());
If you need some special handling for cases, like if amountNumbers< userNumbers.Count or amountNumbers == 1 you need to add that separately. If you know that amountNumbers == userNumbers.Count, then the .Take(...) is not needed.

Error ORA-00907 Right parenthesis missing

Hello i have a long SQL Query for Oracle DB. My Problem is i'm searching for arround 2 hours to get the error fixed. On all Queries i have the same error with parenthesis.
Here is my class where i get the error inside the command of OracleDB Query. I didnt find the error. The Query shown below is working on Delphi without problems. The only thing i change are the quotation marks at the beginning and at the end of each line which a normally single quoted.
using System;
using System.Windows.Forms;
using Oracle.ManagedDataAccess.Client;
namespace RawBinderLabel
{
public partial class Rawbinder_Manually : Form
{
private database_conn db_conn = new database_conn();
private OracleConnection OraConn = new OracleConnection();
public Rawbinder_Manually()
{
InitializeComponent();
get_rawbinder_data();
}
public void get_rawbinder_data()
{
string rcs = db_conn.connection();
using (OracleConnection OraConn = new OracleConnection(rcs))
{
using (OracleCommand OraCmd = OraConn.CreateCommand())
{
try
{
OraConn.Open();
OraCmd.BindByName = true;
//SQL Command to retrieve manual binder that ar OK
OraCmd.CommandText = "SELECT l.a_layer_pos, " +
" l.a_serial, " +
" P_ROHBINDER_ETIKETTEN.GET_BARCODE (mb.a_serial,''M'') Barcode, " +
" mb.a_splitted," +
" mb.a_dlam, " +
" l.a_order_id, " +
" l.a_section_id, " +
" P_ROHBINDER_ETIKETTEN.GET_MANUALPOSITIONS (mb.a_serial) Positionen, " +
" P_ROHBINDER_ETIKETTEN.GET_MANUALABBUND (mb.a_serial) abbund, " +
" P_ROHBINDER_ETIKETTEN.GET_MANUALQUALITY (mb.a_prodquality_id) qualitaet, " +
" to_char(lt.LIEFERTERMIN, ''dd.mm.yyyy'') liefertermin, " +
" ''1'' a_beam_pos, " +
" P_ROHBINDER_ETIKETTEN.GET_MAXMANUALLENGTH (l.a_serial) max_a_length, " +
" substr(c.a_cust_name,1,40) kunde, " +
" l.a_dimter_start_date, " +
" l.a_dimter_end_date, " +
" p.a_prod_date, " +
" p.a_destheight, " +
" p.a_description, " +
" dl.a_layer_serial, " +
" dl.a_width, " +
" dl.a_lamellaheight, " +
" dl.A_RAWWIDTH, " +
" dl.A_RAWLAMELLAHEIGHT, " +
" dl.A_GLUE_DESCRIPTION, " +
" dl.A_COLOR_DESCRIPTION, " +
" dl.a_pressproc_description, " +
" dl.a_pressproc_description ||' - ' || p.a_description || '' - ('' ||p.a_destlength || '')'' pressbett, " +
" mb.a_serial beam_serial," +
" mb.a_prodquality_id," +
" FROM t_manual_layer l," +
"t_manual_pressproc p, " +
"t_dimter_layer dl, " +
"t_manualbeam mb, " +
"v_liefertermin lt, " +
"t_order o, " +
"t_customer c " +
" WHERE to_char(p.a_prod_date,''DD.MM.YYYY'') = ''' :rawbinder_date '''" +
" and p.a_pressproc_id = l.a_pressproc_id " +
" AND l.A_SERIAL = dl.A_SERIAL " +
" AND mb.A_LAYER_SERIAL = l.a_serial " +
" AND lt.PROJEKTNR = l.a_order_id " +
" AND lt.GPID = l.a_section_id " +
" AND o.a_order_id = l.a_order_id " +
" and c.a_customer_id = o.a_customer_id " +
" order by l.A_SERIAL, l.a_layer_pos";
//Assign Parameters to Date selected in Overview Form
OracleParameter rawbinder_date = new OracleParameter("rawbinder_date", RawBinder_Overview.rawbinder_date);
OraCmd.Parameters.Add(rawbinder_date);
//Execute the command and display it using DataReader
OracleDataReader OraDataRead = OraCmd.ExecuteReader();
while (OraDataRead.Read())
{
Console.WriteLine("Manually Implemented" + OraDataRead.GetString(0));
}
}
catch (OracleException ex)
{
switch (ex.Number)
{
case 1:
MessageBox.Show("Fehler beim Einfügen der Daten");
break;
case 12560:
MessageBox.Show("Die Datenbank ist nicht erreichbar.");
break;
default:
MessageBox.Show("Datenbankfehler: " + ex.Message.ToString());
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
finally
{
OraConn.Dispose();
}
}
}
}
}
}
Does someone has an Idea how to fix that Problem?
I think there are multiple issues:
2 times single quotes are not required everywhere
comma after " mb.a_prodquality_id," + is not required as it is the last expression of SELECT clause
as mentioned in the comment by #crowcoder, single quotes around parameters are not required. Means around this: :rawbinder_date
Try to solve all this problems and check if it executes properly.

HttpClient put issue in Angular

I'm developing an Angular app with Web api.
I have created a service (sellerService) in which I can update some data in my database with HttpClient put.
Above works but it update all the data of my table, something like follows;
Before I update my seller:
After I update my seller:
My sellerService code:
updateSeller(user: string, nbsales: number, pVote: number, nVote: number, idUser: number): Observable<any> {
return this.http.put('http://localhost:50867/api/seller_user/', {
'username': user,
'nbSales': nbsales,
'positiveVote': pVote,
'negativeVote': nVote,
'idUser': idUser
});
}
My update query (DAO (c#)):
public static readonly string UPDATE = "update " + TABLE_NAME + " set "
+ COLUMN_USERNAME + " =#username"
+ ", " + COLUMN_NB_SALES + "=#nbSales"
+ ", " + COLUMN_POSITIVE_VOTE + "=#positiveVote"
+ ", " + COLUMN_NEGATIVE_VOTE + " =#negativeVote"
+ ", " + COLUMN_ID_USER + "=#idUser";
//Update a seller_user
public static bool Update(Seller_user todo)
{
bool state = false;
using (SqlConnection connection = DataBase.GetConnection())
{
connection.Open();
SqlCommand command = new SqlCommand(UPDATE, connection);
//command.Parameters.AddWithValue("#idSeller", todo.idSeller);
command.Parameters.AddWithValue("#username", todo.username);
command.Parameters.AddWithValue("#nbSales", todo.nbSales);
command.Parameters.AddWithValue("#positiveVote", todo.positiveVote);
command.Parameters.AddWithValue("#negativeVote", todo.negativeVote);
command.Parameters.AddWithValue("#idUser", todo.idUser);
state = command.ExecuteNonQuery() != 0;
}
return state;
}
Thanks in advance ;)
You missed where clause in SQL query. So it will update all records.
public static readonly string UPDATE = "update " + TABLE_NAME + " set "
+ COLUMN_USERNAME + " =#username"
+ ", " + COLUMN_NB_SALES + "=#nbSales"
+ ", " + COLUMN_POSITIVE_VOTE + "=#positiveVote"
+ ", " + COLUMN_NEGATIVE_VOTE + " =#negativeVote"
+ ", " + COLUMN_ID_USER + "=#idUser"
+ "WHERE " + COLUMN_ID_USER + "=" + "= #idUser";

DatagridView boolean values update to database

I'm having an issue when I update values from a datagridview row to the database. The issue is that I have designed the table in the DB with certain fields as "bit" data type to store boolean value flags.
When i assign the datatable to the datagridview the system aytomatically displays these certain fields as checkboxes, which suits me just fine.
But when I try to update these values back to the database the boolean values go bananas.....Here is my code...
int fragileChk = (Convert.ToBoolean(aRow.Cells[12].Value) ? 1 : 0);
int inflamChk = (Convert.ToBoolean(aRow.Cells[13].Value) ? 1 : 0);
int biologicalChk = (Convert.ToBoolean(aRow.Cells[15].Value) ? 1 : 0);
int emergencyChk = (Convert.ToBoolean(aRow.Cells[16].Value) ? 1 : 0);
int usedChk = (Convert.ToBoolean(aRow.Cells[25].Value) ? 1 : 0);
int offerChk = (Convert.ToBoolean(aRow.Cells[27].Value) ? 1 : 0);
string err;
string sqlComm = "UPDATE [70_warehouse_lines] SET " +
"ProductDescr = '" + aRow.Cells[5].Value.ToString() + "', " +
"PartNumber = '" + aRow.Cells[6].Value.ToString() + "', " +
"SerialNumber = '" + aRow.Cells[7].Value.ToString() + "', " +
"Quanitity = " + aRow.Cells[8].Value + ", " +
"Weight = " + aRow.Cells[10].Value + ", " +
"FragileFlag = " + fragileChk + ", " +
"InflammableFlag =" + inflamChk + ", " +
"BiologicalFlag = " + biologicalChk + ", " +
"EmergencyFlag = " + emergencyChk + ", " +
"SpecialInstructions = '" + aRow.Cells[17].Value.ToString() + "', " +
"ShopCostPrice = " + aRow.Cells[19].Value + ", " +
"RetailPrice1 = " + aRow.Cells[20].Value + ", " +
"RetailPrice2 = " + aRow.Cells[21].Value + ", " +
"WholePrice1 = " + aRow.Cells[22].Value + ", " +
"WholePrice2 = " + aRow.Cells[23].Value + ", " +
"CalculatedPrice = " + aRow.Cells[24].Value + ", " +
"UsedParts = " + usedChk + ", " +
"TimesProcessed = " + aRow.Cells[26].Value + ", " +
"OnOffer = " + offerChk + ", " +
"NotesPerPart = '" + aRow.Cells[28].Value.ToString() + "' " +
"WHERE WarehouseLineID = '" + aRow.Cells[0].Value.ToString() + "'";
myConn.ExecSqlCmd(sqlComm, out err);
any ideas ? (I have declared int values just for diagnostic purposes. Thank you in advance for your help.
Always use parameterised query, Using parameters helps prevent SQL Injection attacks when the database is used in conjunction with a program interface.
also you can specify datatype in parameterised query that will helpfull in your case.
string sqlComm = "UPDATE [70_warehouse_lines] SET " +
"ProductDescr = #ProductDescr " +
"PartNumber = #PartNumber " +
"SerialNumber = #SerialNumber " +
"Quanitity = #Quanitity" +
"Weight = #Weight" +
"FragileFlag = #FragileFlag" +
"InflammableFlag = #InflammableFlag" +
"BiologicalFlag = #BiologicalFlag" +
"EmergencyFlag = #EmergencyFlag" +
"SpecialInstructions = #SpecialInstructions " +
"ShopCostPrice = #ShopCostPrice" +
"RetailPrice1 = #RetailPrice1" +
"RetailPrice2 = #RetailPrice2 " +
"WholePrice1 = #WholePrice1 " +
"WholePrice2 = #WholePrice2 " +
"CalculatedPrice = #CalculatedPrice " +
"UsedParts = #UsedParts " +
"TimesProcessed = #TimesProcessed " +
"OnOffer = #OnOffer " +
"NotesPerPart = #NotesPerPart" +
"WHERE WarehouseLineID = #WarehouseLineID ";
MySqlCommand cmd = new MySqlCommand(sqlComm);
cmd.Parameters.Add("#FragileFlag", MySqlDbType.Bit).Value = (Convert.ToBoolean(aRow.Cells[12].Value) ? 1 : 0);
cmd.Parameters.Add("#InflammableFlag", MySqlDbType.Bit).Value=(Convert.ToBoolean(aRow.Cells[13].Value) ? 1 : 0);
cmd.Parameters.Add("#BiologicalFlag", MySqlDbType.Bit).Value=(Convert.ToBoolean(aRow.Cells[15].Value) ? 1 : 0);
cmd.Parameters.Add("#EmergencyFlag", MySqlDbType.Bit).Value = (Convert.ToBoolean(aRow.Cells[16].Value) ? 1 : 0);
....................................
....................................
....................................
and so on
cmd.ExecuteNonQuery();

C# adding every table row to textbox from database

I've been working a bit with binding database tables to text boxes and I've encountered a problem. The code I have here gets all the columns I need from the table, but only 1 row's worth of data shows up. Is there a simple way to make every single row from the table appear in a text box? Or some other sort of text list?
SqlConnection cn = new SqlConnection("SERVER=myserver;DATABASE=mydb;Trusted_Connection=True");
SqlCommand cmd = new SqlCommand();
SqlDataReader dr = null;
cmd.Connection = cn;
cn.Open();
cmd.CommandText = "SELECT DisasterID,DisasterType,Location,CurrentStatus,IntensityLevel,Latitude,Longitude FROM Disasters";
dr = cmd.ExecuteReader();
if (dr.Read()) {
txtFeeds.Text = dr["DisasterID"].ToString() + " " + dr["DisasterType"].ToString() + " " + dr["Location"].ToString() + " " + dr["CurrentStatus"].ToString() + " " + dr["IntensityLevel"].ToString() + " " + dr["Latitude"].ToString() + " " + dr["Longitude"].ToString();
}
cn.Close();
You need while loop and append each line to textbox by txtFeeds.Text +=
while(dr.Read()) {
txtFeeds.Text += dr["DisasterID"].ToString() + " "
+ dr["DisasterType"].ToString() + " "
+ dr["Location"].ToString() + " "
+ dr["CurrentStatus"].ToString() + " "
+ dr["IntensityLevel"].ToString() + " "
+ dr["Latitude"].ToString() + " " + dr["Longitude"].ToString();
}
If you need more performance you can use StringBuilder to append text and finally set textbox text using StringBuilder.ToString method.
Edit.
StringBuilder sb = new StringBuilder();
while (dr.Read())
{
sb.AppendLine(dr["DisasterID"].ToString() + " "
+ dr["DisasterType"].ToString() + " "
+ dr["Location"].ToString() + " "
+ dr["CurrentStatus"].ToString() + " "
+ dr["IntensityLevel"].ToString() + " "
+ dr["Latitude"].ToString() + " " + dr["Longitude"].ToString());
}
txtFeeds.Text = sb.ToString();
First of all its a bad idea trying display records from a table in a single textbox.
If you still want to do it,
Use a while loop instead of IF condition
while(dr.Read())
{
}
Use a string builder and append all your column values to it and after while loop exists use the values in the string builder and set it to the field.
StringBuilder values = new StringBuilder();
while(dr.Read()) {
values.Append( dr["DisasterID"].ToString() + " " + dr["DisasterType"].ToString() + " " + dr["Location"].ToString() + " " + dr["CurrentStatus"].ToString() + " " + dr["IntensityLevel"].ToString() + " " + dr["Latitude"].ToString() + " " + dr["Longitude"].ToString());
}
txtFeeds.Text = values.ToString();

Categories