How could I take the following code and make each iteration of myValues asynchronous (in regards to executing the command, not the loop itself)?
using (var connection = new SqlConnection(CONNECTION_STRING))
using (var command = new SqlCommand(query, connection))
{
connection.Open();
command.Parameters.Add("#myParameter", SqlDbType.VarChar)
foreach(string myValue in myValues)
{
command.Parameters["#myParameter"].Value = myValue;
using (var dr = command.ExecuteReader(CommandBehavior.SingleResult))
{
while (dr.Read())
{
//do something
}
}
}
}
Is this what you need?
private void MyMethod()
{
UpdateValues();
}
async Task UpdateValues()
{
using (var connection = new SqlConnection("your_connection_string_here"))
{
using (var command = new SqlCommand("your_sql_statement_here", connection))
{
await connection.OpenAsync();
command.Parameters.Add("#myParameter", SqlDbType.VarChar);
foreach (string myValue in myValues)
{
command.Parameters["#myParameter"].Value = myValue;
var dr = await command.ExecuteReaderAsync(CommandBehavior.SingleResult);
while (await dr.ReadAsync())
{
// do your thing here //
}
}
}
}
}
Related
I have the following code but it only reads the last part of the JSON value:
public string GetUsersJson(long systemOrgId)
{
var query = #"DECLARE #OrgId bigint = #systemOrgId
SELECT e.OrgId, e.Id, e.FirstName, e.LastName
FROM [Internal].[Employee] e
WHERE OrgId = #OrgId and IsActive=1
FOR JSON PATH, ROOT('Users');";
var json = ExecuteSqlCommandWithJsonResponse(query, systemOrgId);
return json;
}
private string ExecuteSqlCommandWithJsonResponse(string queryString, long systemOrgId)
{
var result = "";
using (SqlConnection connection = new SqlConnection(_systemConnectionString))
{
using (var cmd = connection.CreateCommand())
{
connection.Open();
cmd.CommandText =queryString;
cmd.Parameters.AddWithValue("#systemOrgId", systemOrgId);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result = reader.GetString(reader.GetOrdinal("JSON_F52E2B61-18A1-11d1-B105-00805F49916B"));
}
}
}
}
return result;
}
If I use if instead I get the first part.
if (reader.Read())
{
result = reader.GetString(reader.GetOrdinal("JSON_F52E2B61-18A1-11d1-B105-00805F49916B"));
}
According to the SqlDataReader Class documentation a while (reader.Read()) should be used.
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqldatareader?view=dotnet-plat-ext-7.0#examples
Adapting the code to look more like the MS example also gives the same result:
private string ExecuteSqlCommandWithJsonResponse(string queryString, long systemOrgId)
{
var result = "";
using (SqlConnection connection = new SqlConnection(_systemConnectionString))
{
var cmd = connection.CreateCommand();
connection.Open();
cmd.CommandText = queryString;
cmd.Parameters.AddWithValue("#systemOrgId", systemOrgId);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
result = reader.GetString(reader.GetOrdinal("JSON_F52E2B61-18A1-11d1-B105-00805F49916B"));
}
reader.Close();
}
return result;
}
Using a standard concatenate strings with += easily solved it. I hope this can help someone else since this information is missing in the examples I have seen.
https://learn.microsoft.com/en-us/dotnet/csharp/how-to/concatenate-multiple-strings#-and--operators
private string ExecuteSqlCommandWithJsonResponse(string queryString, long systemOrgId)
{
var result = "";
using (SqlConnection connection = new SqlConnection(_systemConnectionString))
{
using (var cmd = connection.CreateCommand())
{
connection.Open();
cmd.CommandText =queryString;
cmd.Parameters.AddWithValue("#systemOrgId", systemOrgId);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result += reader.GetString(reader.GetOrdinal("JSON_F52E2B61-18A1-11d1-B105-00805F49916B"));
}
}
}
}
return result;
}
I'm trying to make a method. So I will be able to get result of a queryText. But using Dictionary not an option since key has to be unique which in some cases it is not.
The idea is that i should be able to do something like this:
var storeQuery = StoreQuery(query);
storeQuery["first_name"] or storeQuery["last_name"]
public Dictionary<string, object> StoreQuery(string queryText)
{
Dictionary<string, object> queryDictionary = new Dictionary<string, object>();
using (MySqlConnection connection = CreateConnection())
{
using (MySqlCommand command = new MySqlCommand(queryText, connection))
{
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
queryDictionary.Add(reader.GetName(i), reader.GetValue(i));
}
}
}
}
}
return queryDictionary;
}
As you stated yourself you can't have a Dictionary with keys which are not unique, so both options in my answer assumes you need first occurance of the key:
Option 1: using List of Tuples
public List<Tuple<string, string>> StoreQuery(string queryText)
{
List<Tuple<string, string>> queryList = new List<Tuple<string, string>>();
using (MySqlConnection connection = CreateConnection())
{
using (MySqlCommand command = new MySqlCommand(queryText, connection))
{
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
queryList.Add(reader.GetName(i), reader.GetValue(i));
}
}
}
}
}
return queryList;
}
Usage:
var storeQuery = StoreQuery(query);
storeQuery.FirstOrDefault(x => string.Equals(x.Item1, "first_name"));//this will return first oocurance of "first_name" as a key
Option 2: using List of KeyValuePairs:
public List<KeyValuePair<string, string>> StoreQuery(string queryText)
{
List<KeyValuePair<string, string>> queryList = new List<KeyValuePair<string, string>>();
using (MySqlConnection connection = CreateConnection())
{
using (MySqlCommand command = new MySqlCommand(queryText, connection))
{
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
queryList.Add(reader.GetName(i), reader.GetValue(i));
}
}
}
}
}
return queryList;
}
Usage:
var storeQuery = StoreQuery(query);
storeQuery.FirstOrDefault(x => string.Equals(x.Key, "first_name"));//this will return first oocurance of "first_name" as a key
real newbie question and I would appreciate any support you could offer.
I am trying to output SQL results to a list. But when I return the list I get
System.Collections.Generic.List`1[System.String]
This my code, any ideas? Thank you in advance.
public static List<string> GetDTSXPackages()
{
List<String> packages = new List<String>();
using (SqlConnection connection = new SqlConnection(SQLConnectionString()))
{
string query = "SELECT PackageName FROM SharedServices.DTSXPackages";
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
packages.Add(reader["PackageName"].ToString());
}
}
connection.Close();
}
}
return packages;
}
static void Main(string[] args)
{
List<string> x = SQLAccessLayer.GetDTSXPackages();
foreach (var package in x)
{
Console.WriteLine(x);
}
}
It is not an error
By doing a loop you can see all values
foreach(var i in Packages)
{
Console.WriteLine(i);
}
Change
Console.WriteLine(x);
To
Console.WriteLine(package);
I've got a data access layer to which I am binding some controls. Currently I have something along the lines of
public List<Race> GetRaces()
{
List<Race> raceList = new List<Race>();
using (var con = new SqlConnection(this.ConnectionString))
{
using (var cmd = new SqlCommand("spGetRace",con))
{
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Race r = new Race();
r.RaceId = Convert.ToInt32(rdr["raceId"]);
r.RaceDescription = rdr["RaceDescription"].ToString();
raceList.Add(r);
}
}
return raceList;
}
}
public List<Ses> GetSes()
{
List<Ses> sesList = new List<Ses>();
using (var con = new SqlConnection(this.ConnectionString))
{
using (var cmd = new SqlCommand("spGetSes",con))
{
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Ses s = new Ses();
s.SesId = Convert.ToInt32(rdr["SesId"]);
s.SesDescription = rdr["SesDescription"].ToString();
sesList.Add(s);
}
}
return sesList;
}
}
which will be bound to drop down lists in my presentation layer. Instead of having to type the lion's share of this ADO.NET code over and over, what are some useful refactoring techniques for this basic type of data access? Can I do this by refactoring with a SqlConnection, SqlCommand, and one of my custom types Race/Ses as a parameter?
public enum SqlCommandNames
{
spGetRace,
spGetSes ,
spGetOthers
}
public class myobj{
public int id {get;set;}
public string description {get;set}
}
public List<myobj> GetObj(SqlCommandNames sqlcmd)
{
List<myobj> objList = new List<myobj>();
using (var con = new SqlConnection(this.ConnectionString))
{
using (var cmd = new SqlCommand(sqlcmd.ToString(),con))
{
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
myobj r = new myobj();
r.id = = reader.GetInt32(0);
r.description = reader.IsDBNull(1) ? "" : reader.GetString(1);
objList.Add(r);
}
}
return objList;
}
}
Additional advice will be to cache lists
List<myobj> objList = (List<myobj>)HttpContext.Current.Cache[sqlcmd.ToString()];
if (objList == null)
{
List<myobj> objList = new List<myobj>();
HttpContext.Current.Cache.Insert(sqlcmd.ToString(), objList);
....
....
}
//and caching all on start up
protected void Application_Start()
{
foreach (SqlCommandNames x in Enum.GetValues(typeof(SqlCommandNames)))
{
GetObj(x);
}
}
Hi i want to know if there is a more simplified method than the one im using now to find if there is an entry or not in a mysql db.
public static bool check_db_entry(string query)
{
using (var conn = new MySqlConnection(DbMethods.constr))
{
using (var cmd = new MySqlCommand(query, conn))
{
conn.Open();
using (var rdr = cmd.ExecuteReader())
{
if (rdr.Read() == false)
{
return false;
}
else
{
return true;
}
}
}
}
}
Leaving aside for now that fact that methods that accept only sql strings are inherently unsafe, this smells wrong to me. If you're going to have public methods that accept arbitrary sql commands (remember: I said "If"), then undoubtedly you have one that returns the data directly. You should rely on that as your base. Here's an example:
private static IEnumerable<IDataRecord> GetDataImpl(string query)
{
using (var conn = new MySqlConnection(DbMethods.constr))
using (var cmd = new MySqlCommand(query, conn))
{
conn.Open();
using (var rdr = cmd.ExecuteReader())
{
yield return rdr;
}
}
}
public static bool check_db_entry(string query)
{
return GetDataImpl(query).Any();
}
Note there is a reason I listed the first method as private. As written, it can have weird side effects if you don't first copy each element in the reader before returning it to a higher abstraction level in your program. But you can get the public version easily enough:
public static IEnumerable<T> GetData<T>(string query, Func<IDataRecord,T> copy)
{
return GetDataImpl(query).Select(copy);
}
Taking aside your design issues pointed in the question's comments, if you want to check the existence an entry in the database, you should always query with COUNT(*): SELECT COUNT(*) FROM yourTable [WHERE theCondition].
If that is all you pass to your function, you can then simply with:
public static bool check_db_entry(string query)
{
using (var conn = new MySqlConnection(DbMethods.constr))
{
conn.Open();
using (var cmd = new MySqlCommand(query, conn))
{
return (int)cmd.ExecuteScalar() == 1;
}
}
}
And if you want to streamline it:
public static bool check_db_entry(string query)
{
using (var conn = new MySqlConnection(DbMethods.constr))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = query;
return (int)cmd.ExecuteScalar() == 1;
}
}