I'm a new C# coder and I am also new with Microsoft SQL Server. The code I have written will parse data from a file using filehelpers and then will place that data in a SQL table. My question is whether it can parse the data but only place part of the string in the SQL server. For example, here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FileHelpers;
using System.Data.SqlClient;
using System.IO;
namespace OnQ_prototype
{
class Report
{
[DelimitedRecord("\t")]
[IgnoreEmptyLines()]
public class ColumnReportNames
{
public String textbox22;
public String textbox29;
public String textbox24;
public String textbox23;
public String PSFullAcct;
public String AccountDescription;
public String BusDateAmount;
public String ThisPTDAmount;
public String LastPTDAmount;
public String ThisYTDAmount;
public String LastYTDAmount;
public String BusDatePctAvail;
public String ThisPTDPctAvail;
public String LastPTDPctAvail;
public String ThisYTDPctAvail;
public String LastYTDPctAvail;
}
static void ProcessFilesCSVFiles(string originalPath, string destinationPath)
{
foreach (var GenesisDirectory in Directory.GetDirectories(originalPath))
{
foreach (var inputFile in Directory.GetFiles(GenesisDirectory, "*.csv"))
{
string lines = inputFile;
FileHelperEngine engine = new FileHelperEngine(typeof(ColumnReportNames));
var records = engine.ReadFile(lines) as ColumnReportNames[];
foreach (var record in records)
{
SqlCommand cmd;
SqlConnection conn;
conn = new SqlConnection("Data Source=hureports01;Initial Catalog=hureports;Integrated Security=True");
conn.Open();
var sqlCommand = string.Format(#"MERGE [OnQReport] AS target USING (select #Property as Property, #Date_of_Report as Date_of_Report, #Percent_Occupancy_PAR as Percent_Occupancy_PAR, #val as {0}) AS source ON (target.Date_of_Report = source.Date_of_Report) WHEN MATCHED THEN UPDATE SET {0}= source.{0} WHEN NOT MATCHED THEN INSERT (Property, Date_of_Report, Percent_Occupancy_PAR, {0}) VALUES (source.Property, source.Date_of_Report, Percent_Occupancy_PAR, source.{0});", column);
cmd = new SqlCommand(sqlCommand, conn);
cmd.Parameters.AddWithValue("#Property", record.textbox24);
cmd.Parameters.AddWithValue("#Date_of_Report", record.textbox23);
cmd.Parameters.AddWithValue("#Percent_Occupancy_PAR", amount2);
cmd.Parameters.AddWithValue("#val", amount);
cmd.ExecuteNonQuery();
conn.Close();
}
So one of the values I am adding is Date_of_Report which is located in textbox23. However, the value of textbox23 is Business Date: 6/14/2016. Is there a way for it to only put the date in Date_of_Report (i.e. get rid of "Business Date:"
Try this:
string[] getDate = textBoxVal.Split(':');
string dateOfReport = getDate[1];
Are you storing this as a SQL datetime? You may want to convert it afterward.
Relevant fiddle: https://dotnetfiddle.net/ql40kl
Related
I'm create the application, but i have one question.
The client write the name of user in textbox, example 3 letters and search in database(access) and add the database.
Example: User: Rui.
and search in database all nameuser "Rui".
//libraries
using Microsoft.VisualStudio.OLE.Interop;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
private void textBox1_TextChanged(object sender, EventArgs e)
{
OleDbConnection conexao = new OleDbConnection(string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source= {0}\Teste.accdb", Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)));
List<string> Users = new List<string>();
OleDbCommand STK = new OleDbCommand($"SELECT NÂșCliente, NomeUser, CodigoPostal, NIF", conexao);
STK.CommandText = $" SELECT* FROM MyTable WHERE Str(Lista_Pokemon) like '*{textBox1.Text}*'";
User.Clear();
//this code is invention, probably is wrong
for(int d=0; d<Stk.Count()-1; d++)
User.Add(...);
}
If you can help my thanks. This project is c#, net framework and the database is Access 2010. At the moment I dont create the class, but if you need tell my, i need created.
You need create a DbReader and move to next row until end:
OleDbCommand STK = new OleDbCommand($"SELECT NÂșCliente, NomeUser, CodigoPostal, NIF", conexao);
STK.CommandText = $" SELECT * FROM MyTable WHERE Str(Lista_Pokemon) like '%{textBox1.Text}%'";
Users.Clear();
var reader = STK.ExecuteReader();
while (reader.Read())
Users.Add(reader["Lista_Pokemon"].ToString());
Threading user input into the query text is considered a dangerous practice in terms of security and also not logically unsafe.
It is better to act "according to the book" with parameters:
OleDbCommand STK = new OleDbCommand();
STK.Connection = conexao;
STK.CommandText = "SELECT * FROM tblCliente WHERE User like #userParameter";
STK.Parameters.AddWithValue("#userParameter", $"%{textBox1.Text}%")
Users.Clear();
var reader = STK.ExecuteReader();
while (reader.Read())
Users.Add(reader["User"].ToString());
Look at the following code.
The using operator is used here to release resources - this is important!
var dataSource = Path.Combine(
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
"Teste.accdb");
var builder = new OleDbConnectionStringBuilder();
builder.Provider = "Microsoft.ACE.OLEDB.12.0";
builder.DataSource = dataSource;
var connectionString = builder.ToString();
var sql = "SELECT ..."; // place your query here
using (var connection = new OleDbConnection(connectionString))
{
connection.Open();
using (var command = new OleDbCommand(sql, connection))
using (var reader = command.ExecuteReader())
{
var users = new List<User>();
while (reader.Read())
{
var user = new User();
user.ClientNumber = (int)reader["NÂșCliente"];
user.UserName = (string)reader["NomeUser"];
user.CodigoPostal = (string)reader["CodigoPostal"];
user.NIF = (string)reader["NIF"];
users.Add(user);
}
// return users; // Return data from method
}
}
This class is used for storing user data.
Change the property names and types to the ones you need.
class User
{
public int ClientNumber { get; set; }
public string UserName { get; set; }
public string CodigoPostal { get; set; }
public string NIF { get; set; }
}
And, of course, use parameters in sql queries, as #dovid showed in his example.
Thanks Alexander Petrov and dovid, givend the solution to my problem. But i "found" the solution and i send.
OleDbConnection conexao = new OleDbConnection(string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source= {0}\Teste.accdb", Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)));
OleDbCommand STK = new OleDbCommand("SELECT * FROM MyTable ORDER BY Id");
conexao.Open();
comando.Connection = STK;
var reader = comando.ExecuteReader();
var users = new List<User>();
while (reader.Read())
{
var user = new User();
user.ClientNumber = (reader["ClientNumber "]);
user.UserName= reader["UserName"];
user.CodigoPostal= reader["CodigoPostal"];
user.NIF= reader["NIF"];
users.Add(user);
}
class User
{
public string ClientNumber { get; set; }
public string UserName { get; set; }
public string CodigoPostal { get; set; }
public string NIF { get; set; }
}
I am using FileHelpers to read a CSV with the intent of loading a SQL Server table.
The CSV looks something like this:
ID, SOMESTRING
"10","Blah blah"
"11",""
"12","More blah blah"
My Record Mapping class looks something like this:
[IgnoreFirst, DelimitedRecord(",")]
class Mytable
{
[FieldQuoted]
public ulong Id;
[FieldQuoted]
[FieldNullValue(typeof(string), null)]
public string SomeString;
}
Finally, the code to bulk copy to the DB is:
SqlBulkCopy bc = new SqlBulkCopy(mySqlConnection);
bc.DestinationTableName = "dbo.MYTABLE";
bc.WriteToServer(new FileHelperEngine<Mytable>().ReadFile(baseDir + "\\" + "MYTABLE.CSV").ToDataTable<Mytable>());
Initially, I did not include the FieldNullValue attribute, but including it or not does not appear to matter. In both cases, row 11 imports as an empty string in SQL Server. I would like it to be NULL. Can this be done?
With FileHelpers an empty string will be parsed as String.Empty, but you can override this with a custom converter:
public class EmptyStringConverter : ConverterBase
{
public override object StringToField(string sourceString)
{
if (String.IsNullOrWhiteSpace(sourceString))
return null;
return sourceString;
}
}
Then you define your record class property like this
[FieldConverter(typeof(EmptyStringConverter))]
public string SomeString;
If the string corresponding to SomeString is empty or blank, it will be converted to null.
If you meant using CsvHelper. Yes, it can be done. I was able to test your scenario and was able to verify attribute SOMESTRING = NULL while using Microsoft SQL Server Management Studio 2014.
In my example, using CsvHelper to convert a CSV file into a DataTable, then converting any field that is empty into DBNull.Value.
Inserting the Modified DataTable into Database using Database Stored Procedure and using User-Defined Table Types
Finally, reading from the Database -> DataTable and view the records in DataGridView.
Your will notice empty fields are NULL.
Create a TYPE
CREATE TYPE [dbo].[MyProductTableType] AS TABLE(
[ID] [nvarchar](5) NOT NULL,
[SOMETHING] [nvarchar](128) NULL
)
Create a Procedure:
CREATE PROCEDURE [dbo].[InsertTable]
#myTableType MyProductTableType readonly
AS
BEGIN
insert into [dbo].PRODUCTS select * from #myTableType
END
C# Code when using a DataGridView and a Command Button on the Windows.Forms
using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using System.Data.SqlClient;
using CsvHelper;
using System.IO;
namespace Stack_Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var path = #"C:\Temp\MYTABLE.csv";
DataTable dt = readCSV(path);
foreach(DataRow row in dt.Rows)
{
foreach(DataColumn col in dt.Columns)
{
if (row.Field<String>(col) == String.Empty)
{
row.SetField(col, DBNull.Value); //row.SetField(col, "NULL"); // Or set the value to any string value of your choice
}
}
}
SqlConnection conn = new SqlConnection("Your SQL Connection String");
using (var command = new SqlCommand("InsertTable", conn) { CommandType = CommandType.StoredProcedure })
{
command.Parameters.Add(new SqlParameter("#myTableType", dt));
command.Connection.Open();
command.ExecuteNonQuery();
command.Dispose();
dt.Clear();
}
using(var command = new SqlCommand("Select * from PRODUCTS", conn) { CommandType = CommandType.Text})
{
SqlDataReader rdr = command.ExecuteReader();
dt.Load(rdr);
dataGridView1.DataBindings.Clear();
dataGridView1.DataSource = dt;
dataGridView1.Refresh();
dt.Dispose();
command.Dispose();
conn.Close();
conn.Dispose();
}
} // End button1_Click
using CsvHelper
public DataTable readCSV(string filePath)
{
var dt = new DataTable();
var csv = new CsvReader(new StreamReader(filePath));
// Creating the columns
typeof(Product).GetProperties().Select(p => p.Name).ToList().ForEach(x => dt.Columns.Add(x));
// Adding the rows
csv.GetRecords<Product>().ToList().ForEach(line => dt.Rows.Add(line.ID, line.SOMETHING));
return dt;
} // End readCSV : DataTable
A class object
public class Product
{
public string ID { get; set; }
public string SOMETHING { get; set; }
} // End class Product
SQL Server - DB Result Snapshot
I'm not familiar with the FileHelper package you are using but the problem is that the value for row 11 is "" not null.
Maybe you could expand the SomeString property definition, like this
private string _SomeString;
[FieldQuoted]
[FieldNullValue(typeof(string), null)]
public string SomeString { get {return _SomeString;}
set {if (value == null || value.length == 0)
_SomeString = null;
else
_SomeString = value;} }
I need to get from each individual table but from the same column name the value to a string array. Although I don't what I table names I've got. I only know they all have a column name 'email'.
string connectionString = "SERVER=********;PORT=****;DATABASE=********;UID=********;PASSWORD=******;";
MySqlConnection conn = new MySqlConnection(connectionString);
MySqlCommand command = conn.CreateCommand();
try
{
conn.Open();
command.CommandText = "SHOW FULL TABLES FROM ExampleDataBase";
}
catch
{
MessageBox.Show("error");
}
MySqlDataReader reader;
reader = command.ExecuteReader();
while (reader.Read())
{
string usermail = reader.GetString("email");
string[] mail = new String[] { usermail};
foreach (string s in mail)
{
listboxMails.Items.Add("email: " + s)
}
}
Not knowing the table names is not a good start when you work with DB...
First get a list of all table name who have the email field
SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = 'email'
AND TABLE_SCHEMA='ExampleDataBase';
Second generate a UNION request with all your table name
like
(SELECT email FROM %myTable1%)
UNION
(SELECT email FROM %myTable2%)
-- ...
Lacking a name, it might be easiest to use Linq's mapping. Make sure to add the reference System.Linq.Data... Here's the code:
using System.Linq;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
namespace ...
{
class Program
{
static void Main(string[] args)
{
DataContext dataContext = new DataContext(connectionString);
Table<Email> Emails = dataContext.GetTable<Email>();
IQueryable<string> query = from e in Emails
select $"email: {e.email}";
}
}
[Table]
public class Email
{
[Column(IsPrimaryKey = true)]
public string email;
}
}
This should be the easiest way to enumerate. I hope this helps.
Im very new on C#
I Only create 1 Form that Can insert Data to Mysql Database. My code not have Error, but data cant enter the Database. I m so confused.
this my code
Koneksi.cs
using System;
using System.Data;
using MySql.Data.MySqlClient;
using System.Drawing;
using System.Windows.Forms;
namespace timbangan
{
public class Koneksi
{
public MySqlConnection konek;
//string konfigKoneksi = "server=localhost; database=timbangan; uid=root; pwd=";
string konfigKoneksi = "Server=localhost;Database=timbangan;Uid=root;Pwd=";
public void bukaKoneksi()
{
konek = new MySqlConnection(konfigKoneksi);
konek.Open();
var temp = konek.State.ToString();
if (temp == "Open")
{
MessageBox.Show(#"Connection working.");
}
else {
MessageBox.Show(#"Please check connection string");
}
}
public void tutupKoneksi()
{
konek = new MySqlConnection(konfigKoneksi);
konek.Close();
}
}//end of koneksi
}//end namespace
Isidata.cs File
using System;
using System.Data;
using MySql.Data.MySqlClient;
using System.Windows.Forms;
namespace timbangan
{
public class Isidata
{
MySqlDataAdapter adapter;
MySqlCommand komand;
Koneksi classKoneksi;
DataTable tabel;
string sql = "";
public DataTable tambahData(string berat_filter, string qty, string nama_barang, string dari, string shift)
{
classKoneksi = new Koneksi();
sql = "insert into tb_timbang(BERAT_FILTER,QTY,NAMA_BARANG,DARI,SHIFT) values (" + berat_filter + ",'" + qty + "','" + nama_barang + "','" + dari + "','" + shift + "')";
//MessageBox.Show(sql);
tabel = new DataTable();
try
{
classKoneksi.bukaKoneksi();
komand = new MySqlCommand(sql);
adapter = new MySqlDataAdapter(sql, classKoneksi.konek);
adapter.Fill(tabel);
}
catch (Exception)
{
MessageBox.Show("error");
}
return tabel;
}
}//end of issdata
}//end of timbangan
Form1.cs File
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
namespace timbangan
{
public partial class Form1 : Form
{
public DataTable tabel;
public string status = "";
public string berat_filter, qty, nama_barang, dari, shift;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Isidata isi = new Isidata();
tabel = isi.tambahData(tbBerat.Text, tbQty.Text, tbNama.Text, tbDari.Text, tbShift.Text);
MessageBox.Show("Berhasil");
}
}
}
Can Anyone Help me to Fix this? or Advice me to have more short code to Insert data?
Thanks in advance
You could redesign your classes to something like this
namespace timbangan
{
public static class Koneksi
{
public static MySqlConnection konek;
private static string konfigKoneksi = "Server=localhost;Database=timbangan;Uid=root;Pwd=";
public static MySqlConnection GetConnection()
{
konek = new MySqlConnection(konfigKoneksi);
konek.Open();
}
}//end of koneksi
public class Isidata
{
public int InsertData(string berat_filter, string qty, string nama_barang, string dari, string shift)
{
sql = #"insert into tb_timbang
(BERAT_FILTER,QTY,NAMA_BARANG,DARI,SHIFT)
values (#berat_filter,#qty,#nama_barang,#dari,#shift)";
try
{
using(MySqlConnection cnn = Koneksi.GetConnection())
using(MySqlCommand cmd = new MySqlCommand(sql, cnn))
{
cmd.Parameters.Add("#berat_filter", MySqlDbType.VarChar).Value = berat_filter;
cmd.Parameters.Add("#qty", MySqlDbType.VarChar).Value = qty;
cmd.Parameters.Add("#name_barang", MySqlDbType.VarChar).Value = nama_barang;
cmd.Parameters.Add("#dari", MySqlDbType.VarChar).Value = dari;
cmd.Parameters.Add("#shift", MySqlDbType.VarChar).Value = shift;
return cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show("error " + ex.Message);
return -1;
}
}
}
}//end of issdata
}//end of timbangan
In this design there are no more global variables around. The same Koneski class could be totally removed and your MySqlConnection could be created on the spot (reading the connectionstring from an external source like your config file). Don't think this is less efficient than keeping a global connection object already created and always open. There is an ADO.NET Connection Pooling infrastructure (link is for Sql Server but it is the same for MySql) that runs very efficiently to handle your connections
The important thing is the Using Statement (that closes and dispose the command and the connection when no more needed freeing valuable resources) and the parameters used to fill the command sent to the server. If you need to use an Adapter for other aspect of your work you could add other methods like this to your Isidata class
As a last note, notice that all parameters are of string type. This could work but it is best to have parameters of the same type of the field type on the database (and of course your variables should be of the correct datatype). This is particularly important with datetime fields that when are treated as strings could give a good headache to let them work correctly) See MySqlDbType enum
Make a class named DBClass.cs and write the below code-
class DBClass
{
MySqlCommand odcmd = new MySqlCommand();
MySqlConnection odcon = new MySqlConnection();
MySqlDataAdapter oda = new MySqlDataAdapter();
public DBClass()
{
}
public void OpenConnection()
{
odcon.ConnectionString = "Server=localhost;Database=timbangan;Uid=root;Pwd=";
if (odcon.State == ConnectionState.Closed)
odcon.Open();
oda.SelectCommand = odcmd;
odcmd.Connection = odcon;
}
public void CloseConnection()
{
if (odcon.State == ConnectionState.Open)
odcon.Close();
}
public DataTable Select(string sql)
{
DataTable dt = new DataTable();
odcmd.CommandText = sql;
oda.Fill(dt);
return dt;
}
public int ModiFy(string sql)
{
odcmd.CommandText = sql;
return odcmd.ExecuteNonQuery();
}
}
On your form, Now you can fire your query like-
DbclassObject.Modify(Your_Insert_Update_Delete_Query);
DataTable dt= DbclassObject.Select(Your_Select_Query);
I have a large and somewhat complex SQL script that I'm using in .Net as below..
using System.Data.SqlClient;
using System.IO;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string sqlConnectionString = "Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True";
FileInfo file = new FileInfo("C:\\myscript.sql");
string script = file.OpenText().ReadToEnd();
SqlConnection conn = new SqlConnection(sqlConnectionString);
Server server = new Server(new ServerConnection(conn));
server.ConnectionContext.ExecuteNonQuery(script);
}
}
}
Inside of the SQL script I have an ID value that needs to be a parameter that I pass in from my code, How can I do this? If I use a SQLCommand I could see the script becoming quite complex. Any suggestions or ideas on how to achieve this?
Thanks
You can specify params in file by their index ({0} input to String.Format) and use string.format to provide actual value in code.
FileInfo file = new FileInfo("C:\\myscript.sql");
string fileContent = file.OpenText().ReadToEnd();
//fileContent = "Select * from ABC where COL1 = '{0}'";
string Col1Value = "Col1Values";
string fileString = String.Format(fileContent,Col1Value);