C# passing a string to an Sqlite parameter - c#

I'm trying to pass a string (the output of a function) to an SqLite query and have it update a database with it. I get an error telling me that string is not a valid data type.
IList<string> classList = new List<string>(){ "Saber", "Archer", "Lancer", "Rider",
"Caster", "Assassin", "Berserker", "Ruler", "Avenger", "Moon Cancer"};
public string setClass(int uid)
{
string newClass;
int remainder = uid % 10;
newClass = classList[remainder];
return(newClass);
}
[NadekoCommand, Usage, Description, Aliases]
public async Task initialiseClasses()
{
using (SqliteConnection _db = new SqliteConnection(#"Filename=.\myDb.db"))
{
_db.Open();
string newSQL = "ALTER TABLE DiscordUser ADD Class char";
SqliteCommand command = new SqliteCommand(newSQL, _db);
command.ExecuteReader();
string tempClass = setClass(7); //temporary input
newSQL = "UPDATE DiscordUser SET Class = #newClass";
command.Parameters.Add(new SqliteParameter("#newClass", SqliteType.Text).Value = tempClass);
command = new SqliteCommand(newSQL, _db);
command.ExecuteReader();
}
}
I'm trying to pass tempClass into the Sqlite query.

You were creating a new command after you assigned the parameter to the command which resulted in a command without parameters being executed.
The Add on the parameter collection can be rewritten so it is more fluent, see change below.
ExecuteReader should be ExecuteNonQuery
If you structure your code with using blocks it is easier to see the scope of the command instance. See below:
public async Task initialiseClasses()
{
using (SqliteConnection _db = new SqliteConnection(#"Filename=.\myDb.db"))
{
_db.Open();
string newSQL = "ALTER TABLE DiscordUser ADD Class char";
using(SqliteCommand command = new SqliteCommand(newSQL, _db))
{
command.ExecuteNonQuery();
}
string tempClass = setClass(7); //temporary input
newSQL = "UPDATE DiscordUser SET Class = #newClass";
using(SqliteCommand command = new SqliteCommand(newSQL, _db))
{
command.Parameters.Add("#newClass", SqliteType.Text).Value = tempClass;
command.ExecuteNonQuery();
}
}
}

Related

How to retrieve blob data from MySql table and return it as Json format?

I have a table with three columns
MyDate : DateiIme
MyBlob: blob
Id: String
I want to return MyDate and MyBlob as Json. There can be multiple records in the table.
public class MyData
{
public string? MyDate { get; set; };
public string? MyBlob { get; set; };
}
public async Task<string> GetQueryResult(string Id)
{
MyData data = new MyData();
List<MyData> MyList = new List<MyData>();
string sqlSelect = string.Format("Select MyDate, MyBlob from MyTablee WHERE Id = '{0}'", Id);
try
{
MySqlCommand sqlcmd = new MySqlCommand();
MySqlConnection connetcion = new MySqlConnection(connectionString);
sqlcmd.Connection = connetcion;
sqlcmd.CommandTimeout = 0;
sqlcmd.CommandType = CommandType.Text;
sqlcmd.CommandText = sqlSelect;
connetcion.Open();
using (connetcion)
{
int count = 0;
using (MySqlDataReader reader = sqlcmd.ExecuteReader())
{
while (reader.Read())
{
data.MyDate = reader.GetString(0);
data.MyBlob = reader.GetString(1);
MyList.Add(data);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
var json = JsonSerializer.Serialize(results);
return json;
}
The output in the Postman is:
"{\"MyDate\":\"1/30/2023 9:16:40 PM\",\"MyBlob\":\"#MyBlob\"}"
I am not sure the blob data to JSON conversion is correct. Thank you.
It's probable that your table doesn't contain any BLOB data, but instead contains the literal string #MyBlob in that column.
The cause of this would be using a SQL statement like INSERT INTO MyTablee(MyDate, MyBlob) VALUES(NOW, '#MyBlob');, which inserts the literal text #MyBlob.
Make sure your insert code is constructed as follows:
using var command = connection.CreateCommand();
command.CommandText = "INSERT INTO MyTablee(MyDate, MyBlob) VALUES(NOW(), #blob);";
command.Parameters.AddWithValue("#blob", yourBlobDataHere);
command.ExecuteNonQuery();
In particular, there are no quotes around the parameter name in the INSERT statement, and command parameters are being used to send values, instead of string concatenation.

query string for inserting elements in npgsql

I want to insert data into a row in PostgreSQL from NPGSQL, but there is something wrong with my query string. Can you please suggest modify it?
public IActionResult Create(string item_name, string item_count, string item_size)
{
using var connection = new NpgsqlConnection(connString);
connection.Open();
string query = #"INSERT INTO public.""items""(""item_count"",""item_name"",""item_size"")VALUES ('"+item_count+item_count+item_count+"')";
using var command = new NpgsqlCommand(query, connection);
int result = command.ExecuteNonQuery();
if (result < 0)
{
return Error();
}
return View(nameof(Create));
}
You can do it in this way.
You have forgotten to add "," between the values and also add quotes if the value is string or date.
public IActionResult Create(string item_name, string item_count, string item_size)
{
using var connection = new NpgsqlConnection(connString);
connection.Open();
string query = String.Format(#"INSERT INTO public.""items""(""item_count"",""item_name"",""item_size"")VALUES('{0}','{1}','{2}');" , item_count , item_count ,item_count);
using var command = new NpgsqlCommand(query, connection);
int result = command.ExecuteNonQuery();
if (result < 0)
{
return Error();
}
return View(nameof(Create));
}

INSERT values from a list to database

i want to parse a CSV file, store it in a list then insert values from that list to a database . Here is the sample of my code.
I'm still learning so if it is not clear then i will explain further. But the idea is to parse the csv file, row by row, and then insert each row in my database. Thank you in advance.
public class SKU : List<string[]>
{
public string SKU_ID { get; set; }
public string SKU_Name { get; set; }
public string Code { get; set; }
public string Product_Name { get; set; }
public string DistributionCenter_Name { get; set; }
internal static SKU ParseRow(string row)
{
var columns = row.Split(';');
return new SKU()
{
SKU_ID = columns[0],
SKU_Name = columns[1],
Code = columns[2],
Product_Name = columns[3],
DistributionCenter_Name = columns[4],
};
}
}
In the script i named each column like in the csv file and in my database.
My main is as following
class Programm
{
static void Main(string[] args)
{
var sku_info = ProcessCSV("skutest1.csv");
SqlConnection conn = new SqlConnection();
conn.ConnectionString = #"...";
foreach (var information in sku_info)
{
using SqlConnection connection = new SqlConnection(conn.ConnectionString);
string commandString = ("INSERT INTO SKU VALUES ('" + information.SKU_ID + " "+information.SKU_Name+" "+information.Code+" "+information.Product_Name+" "+information.DistributionCenter_Name+"')");
conn.Open();
SqlTransaction transaction = conn.BeginTransaction();
SqlCommand cmd = new SqlCommand(commandString, conn, transaction);
cmd.ExecuteNonQuery();
transaction.Commit();
}
Console.ReadKey();
}
private static List<SKU> ProcessCSV(string path)
{
return File.ReadAllLines("C:/.../skutest1.csv").Where(row => row.Length > 0).Select(SKU.ParseRow).ToList();
}
}
The fastest way to load a file on the server would be to use BULK INSERT, eg :
BULK INSERT someTable
FROM 'pathtofile`
WITH ( FORMAT = 'CSV' )
You can do something similar by using ADO.NET's SqlBulkCopy class to execute a BULK INSERT operation with data sent from the client. SqlBulkCopy expects either a DataTable or IDbDataReader parameter. You can use CsvHelper' CsvDataReader for this. The CsvDataReader parses a CSV file and produces the IDbDataReader interface needed by SqlBulkCopy.
The code could be as simple as this :
using var txtReader = File.OpenText(pathToCSV);
var reader = new CsvReader(txtReader,CultureInfo.InvariantCulture);
using var dbReader = new CsvDataReader(reader);
var bcp = new SqlBulkCopy(cns);
bcp.ColumnMappings.Add("sku_id","sku_id");
bcp.ColumnMappings.Add("sku_name","sku_name");
...
bcp.DestinationTableName = table;
bcp.WriteToServer(dbReader);
Without the mappings SqlBulkCopy will send the columns in the order they appear in the file. If that doesn't match the order of the table columns, you'll get an error or worse, get mixed up data
Here's a short tutorial on building a parameterized commandstring - this is a much safer way of inserting to your database.
Here's a sample of how you could parameterize your insert:
string commandString = (#"INSERT INTO SKU VALUES (#sku_id, #sku_name, #code, #product_name, #distributioncenter_name");
conn.Open();
SqlTransaction transaction = conn.BeginTransaction();
SqlCommand cmd = new SqlCommand(commandString, conn, transaction);
cmd.Parameters.Add(new SqlParameter("#sku_id", information.SKU_ID));
cmd.Parameters.Add(new SqlParameter("#sku_name", information.SKU_Name));
cmd.Parameters.Add(new SqlParameter("#code", information.Code));
cmd.Parameters.Add(new SqlParameter("#product_name", information.Product_Name));
cmd.Parameters.Add(new SqlParameter("#distributioncenter_name", information.DistributionCenter_Name));
cmd.ExecuteNonQuery();
transaction.Commit();

Must declare the scalar variable in Select command

I am passing a long list of employeeIds to employeeIdlist and I split them into a List. Using this list I am adding parameters to my query.
I am getting the following error
{"Must declare the scalar variable \"#EmployeeId\"."}
public List<versionInfo> GetVersion(string employeeIdlist)
{
DbHelper helper = new DbHelper();
List<versionInfo> empVerInfo = new List<versionInfo>();
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand getVersion = new SqlCommand())
{
getVersion.Connection = conn;
getVersion.CommandText = #"SELECT EmployeeId,Version
FROM [dbo].[EmployeeVersion]
WHERE EmployeeId in (#EmployeeId)";
getVersion.CommandType = CommandType.Text;
List<int> empIds = employeeIdlist.Split(',').Select(int.Parse).ToList();
StringBuilder sb = new StringBuilder();
int i = 0;
foreach (var emp in empIds)
{
// IN clause
sb.Append("#EmployeeId" + i.ToString() + ",");
// parameter
getVersion.Parameters.AddWithValue("#EmployeeId" + i.ToString(), emp);
i++;
}
// getVersion.Parameters.AddWithValue("#EmployeeId", employeeIdlist);
SqlDataReader rdr = getVersion.ExecuteReader();
while (rdr.Read())
{
versionInfo vi = new versionInfo();
vi.employeeId = helper.GetDb<int>(rdr, "EmployeeId");
vi.version = helper.GetDb<decimal>(rdr, "Version");
empVerInfo.Add(vi);
}
rdr.Close();
}
conn.Close();
}
return empVerInfo;
}
Remove the text after the IN
getVersion.CommandText = #"SELECT EmployeeId,Version
FROM [dbo].[EmployeeVersion]
WHERE EmployeeId in (";
then the foreach could build the full list of parameters and texts
foreach (var emp in empIds)
{
sb.Append("#EmployeeId" + i.ToString() + ",");
getVersion.Parameters.AddWithValue("#EmployeeId" + i.ToString(), emp);
i++;
}
after exiting the loop remove the last comma from the StringBuilder
sb.Length--;
finally, complete the command text appending the content of the StringBuilder and do not forget the closing parenthesys for the IN clause.
getVersion.CommandText += sb.ToString() + ")";
Now you can run the command with the correct IN clause and a matching list of parameters
If fails because your string query has one parameter named #EmployeeId and your Command object has many parameters with different names ("#EmployeeId1" is not equal to "#EmployeeId")
It seems like you are trying to apply this approach, which is a good idea.
You are two lines away of getting it to work:
Add this lines:
sb.Lenght--;
getVersion.CommandText = getVersion.CommandText.Replace("#EmployeeId",sb.ToString())
just before:
SqlDataReader rdr = getVersion.ExecuteReader();
After doing that your added parameters will match those #parameters existing in the sql string.
This is just another option. You can achieve the same result in 3 lines of code using Dapper ORM used in Stack Overflow.
You can download via NuGet.
public class VersionInfo
{
public int EmployeeId { get; set; }
public decimal Version { get; set; }
}
class Program
{
public static string connString = "...";
static void Main(string[] args)
{
var result = GetVersion(new List<int> {1, 2});
Console.ReadLine();
}
public static List<VersionInfo> GetVersion(IList<int> employeeIds)
{
using (IDbConnection conn = new SqlConnection(connString))
{
conn.Open();
var entities = conn.Query<VersionInfo>(
#"SELECT EmployeeId, Version from EmployeeVersion WHERE EmployeeId IN #EmployeeIds",
new {EmployeeIds = employeeIds});
return entities.ToList();
}
}
}
On your select statement you have to declare a value for your variable. I have made it an Integer. If it is a text value, then you can use varchar(25).
#"DECLARE #EmployeeId INT
SELECT EmployeeId,Version
FROM [dbo].[EmployeeVersion]
WHERE EmployeeId in (#EmployeeId)";

Creating and then working with parameters in queries

I am writing a small XAML/C#/MySQL database and wanted to create a query that accepts parameters. However, the test query that I am setting up fails when I try to create it
var con = new MySqlConnection(ClsVariables.StrDb);
con.Open();
var command = new MySqlCommand("", con);
command =
new MySqlCommand("Create View r2_Add_Edit_View as SELECT era.contact_id, era.n_family FROM era WHERE era.contact_id = #ContactID", con) command.ExecuteNonQuery();
con.Close();
When I change the #ContactID to a specific number - it works fine.
After that I will need to create a recordset, and pass the parameter to it (but I can ask that in a secondary question).
Thanks as always.
When I change the #ContactID to a specific number - it works fine.
Well, you don't pass the parameter, so just add it to your command:
public class MySqlConnector
{
private readonly string _connString;
public MySqlConnector(string connString)
{
_connString = connString;
}
private MySqlCommand _command;
const string Sql = "Create View r2_Add_Edit_View as SELECT era.contact_id, era.n_family FROM era WHERE era.contact_id = #ContactID";
public void CreateView(int contactId)
{
if(_command == null)
{
_command = new MySqlCommand();
_command.CommandText = Sql;
_command.Connection = _connString;
}
_command.Parameters.AddWithValue("#ContactID", contactId);
_command.ExecuteNonQuery();
_command.Close();
}
}
Try to use Command AddParameters method.
command.Parameters.Add("#ContactID", SqlDbType.Int);
command.Parameters["#ContactID"].Value = value;

Categories