C# SQL Server like command not working with parameters - c#

I tried the solution presented in many topics on the internet, but none of them work. If I don't use parameter method like is working. How can fix that?
Here is my C# code:
string kosul = textbox1.Text ;
kitapAra("kitapAdi", kosul);
public void kitapAra(string by,string kosul,int like = 0)
{
string sql = "select * from kitaplar where kitapDurum = 0 and #byP like #kosulP order by kitapId ";
DataTable dt = DbOperations.cmd_SelectQuery(sql, new List<string> { "#byP", "#kosulP" }, new List<object> { by,kosul });
refreshDataGrid(dt);
}
Here is my SQL connect method:
public static DataTable cmd_SelectQuery(string srCommandText, List<string> lstParameterNames, IList<object> lstParameters, bool blsetCommit = false, int like = 0)
{
if (blsetCommit == true)
{
srCommandText = "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED " + Environment.NewLine + " " + srCommandText;
}
DataTable dsCmdPara = new DataTable();
try
{
using (SqlConnection connection = new SqlConnection(DbOperations.srConnectionString))
{
using (SqlCommand cmd = new SqlCommand(srCommandText, connection))
{
cmd.CommandType = CommandType.Text;
for (int i = 0; i < lstParameterNames.Count; i++)
{
cmd.Parameters.AddWithValue(lstParameterNames[i], lstParameters[i].ToString());
}
using (SqlDataAdapter sqlDa = new SqlDataAdapter(cmd))
{
sqlDa.Fill(dsCmdPara);
return dsCmdPara;
}
}
}
}
return dsCmdPara;
}
I tried them:
DataTable dt = DbOperations.cmd_SelectQuery(sql, new List<string> { "#byP", "#kosulP" }, new List<object> { by,"%" + kosul +"%"});
or:
cmd.Parameters.AddWithValue(lstParameterNames[i],"%" + lstParameters[i].ToString()+"%");
or:
"select * from kitaplar where kitapDurum = 0 and #byP like %#kosulP% order by kitapId ";
or:
"select * from kitaplar where kitapDurum = 0 and #byP like "%" + #kosulP + "%" order by kitapId ";

Related

Splitting my SQL class to support multi connection and stored procedure

I need to create the best architecture for my app to manage my different connections (two) and the stored procedure.
So far I have created one SQL class and do not handle the two connections : I have mixed methods and functions which can be called regardless of the connection (and can crash).
How do I create a Connection class and a DAL ?
My SQL connection class :
namespace GripPicture.Data
{
class Sqlmap
{
static string RmSynchro = "ConnectionRmSynchro";
static string PascomPhoto = "ConnectionPascomPhoto";
private string config;
private OleDbConnection _lConnection = new OleDbConnection();
private OleDbConnection OleConnection
{
get
{
if (_lConnection.State != ConnectionState.Open)
{
if (_lConnection.State != ConnectionState.Connecting)
{
_lConnection.OpenAsync();
}
}
return _lConnection;
}
set { _lConnection = value; }
}
public Sqlmap(bool pIsPascom = false)
{
config = pIsPascom ? ConfigurationManager.AppSettings[PascomPhoto] : ConfigurationManager.AppSettings[RmSynchro];
OleConnection = new OleDbConnection(config);
}
private void Connection()
{
OleConnection.OpenAsync();
}
public int ExcuteUpdate(string pQuery)
{
// Check if connection is closed
OleDbCommand command = new OleDbCommand(pQuery, OleConnection);
return command.ExecuteNonQuery();
}
// This function should reside in your SQL-class.
public IEnumerable<T> ExecuteQueryForList<T>(string pQuery)
{
List<T> items = new List<T>();
Type type = typeof(T);
var data = ExecuteDataTable(pQuery);
foreach (DataRow row in data.Rows)
{
// Object have a constructor with a Datarow
T item = (T)Activator.CreateInstance(typeof(T), row);
PascomPhotoDo element = (PascomPhotoDo)Activator.CreateInstance(typeof(PascomPhotoDo), row);
if ((items.Cast<PascomPhotoDo>()).Any((elem => elem.NumeroContact == element.NumeroContact)))
{
LogHelper.Log("Doublons dans la liste Id Pascom " + element.NumeroContact + " " + element.FirstName + " Atlas " + element.IdParticipantAtlas);
//Console.WriteLine("Doublon dans liste : " + element.NumeroContact + " " + element.FirstName + " Atlas " + element.IdParticipantAtlas);
}
items.Add(item);
}
return items;
}
private DataTable ExecuteDataTable(string pQuery)
{
OleDbDataAdapter dp1 = new OleDbDataAdapter(pQuery, OleConnection);
DataSet ldataSet = new DataSet();
dp1.Fill(ldataSet, "table");
return ldataSet.Tables[0];
}
#region PASCOM
public byte[] GetPictureFromPascom(int pNumeroContact)
{
byte[] lDataPicture = null;
OleDbCommand command = new OleDbCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "itsp_Photo_GetPhotoByContact";
command.Connection = OleConnection;
command.Parameters.Add("#numero_contact", OleDbType.Integer).Value = pNumeroContact;
command.CommandTimeout = 15000;
try
{
lDataPicture = (byte[])command.ExecuteScalar();
}
catch (Exception e)
{
LogHelper.Log("Fail to get picture \n" + " Id Pascom " + pNumeroContact + " " + e.Message);
}
return lDataPicture;
}
public void InsertPictureToDatabase(PascomPhotoDo pPascomPhoto)
{
OleDbCommand command = new OleDbCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "itsp_Photo_CreatePhotoContact";
command.Connection = OleConnection;
command.Parameters.Add("#idContact", OleDbType.Integer).Value = pPascomPhoto.NumeroContact;
command.Parameters.Add("#photo", OleDbType.Binary).Value = pPascomPhoto.PhotoByteReduced;
command.Parameters.Add("#source", OleDbType.VarChar).Value = "blabla";
command.Parameters.Add("#idSalonOrganise", OleDbType.VarChar).Value = "blabla";
command.Parameters.Add("#IdParticipantAtlas", OleDbType.VarChar).Value = pPascomPhoto.IdParticipantAtlas;
command.CommandTimeout = 15000;
try
{
int data = command.ExecuteNonQuery();
}
catch (Exception e)
{
LogHelper.Log(LogTarget.File, "Fail to insert in database", e);
}
}
}
#endregion
}
Then I use my SQL connection by declaring a new object like so :
_sqlRmSynchro = new Sqlmap();
_sqlPascom = new Sqlmap(true);
As you can see I can call some specific function from the wrong connection string...
What do I need ? A DAL ? What does it look like ?

Add string array to SQL query

I have a string array which consists of identifiers. I want to get some values from SQL using these identifiers . Is there a way of adding them with a string value to SqlCommand parameters?
I want to create a query like:
select CaseList from MasterReportData where Id = 1 OR Id = 2 OR Id = 3
This is my C# code:
public static List<string> GetCaseList(string[] masterIdList)
{
try
{
string query = " select CaseList from MasterReportData where #masterId";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(query, conn);
cmd.Parameters.AddWithValue("masterId", ***);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(reader[0].ToString());
}
}
conn.Close();
}
catch (Exception e)
{
var err= 0;
}
return list;
}
There are many different ways you can go about doing this but I prefer to create a temp table of possible values. That way you can do something like
select CaseList from MasterReportData where Id IN(select Id from tempTable)
The best approach (with sql optimization) would be:
Create your Type:
CREATE TYPE dbo.IntTTV AS TABLE
( Id int )
Your Ids:
var ids = new List<int>
{
1,
2,
3,
}
Create a schema:
var tableSchema = new List<SqlMetaData>(1)
{
new SqlMetaData("Id", SqlDbType.Int) // I think it's Int
}.ToArray();
Create the table in C#
var table = ids
.Select(i =>
{
var row = new SqlDataRecord(tableSchema);
row.SetInt32(0, i);
return row;
})
.ToList();
Create the SQL Parameter
var parameter = new SqlParameter();
parameter.SqlDbType = SqlDbType.Structured;
parameter.ParameterName = "#Ids";
parameter.Value = table;
parameter.TypeName = "dbo.IntTTV";
var parameters = new SqlParameter[1]
{
parameter
};
Slightly change your query (this is just an example:)
string query = "select mrd.CaseList from MasterReportData mrd"
+ " inner join #ids i on mrd.Id = i.id";
public static List<string> GetCaseList(string[] masterIdList)
{
List<string> list = new List<string>();
try
{
string query = "select CaseList from MasterReportData where ";
using (SqlConnection conn = new SqlConnection(connString))
{
int i = 0;
SqlCommand cmd = new SqlCommand(query, conn);
for(i = 0; i < masterIdList.Length; i++)
{
var parm = "#ID" + i;
cmd.Parameters.Add(new SqlParameter(parm, masterIdList[i]));
query += (i > 0 ? " OR " : "") + " Id = " + parm;
}
cmd.CommandText = query;
//cmd.Parameters.AddWithValue("masterId", ***);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(reader[0].ToString());
}
}
}
}
catch (Exception e)
{
e.ToString();
}
return list;
}

How should I merge these two methods?

hello, guys!
i asked familiar question once and now i'm stuck again
what is a better way to refactor this?
ps. do not want to pass query as a parameter, searching for the most elegant solution
method1
public static List<string> GetWinners(Prize prize)
{
List<string> winners = new List<string>();
using (OleDbConnection connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["ForteLotteryDataConnectionString"].ConnectionString))
{
var query = string.Concat(
#"
SELECT Member.IBAN ",
"FROM Member, Summary ",
"WHERE Member.ID = Summary.WinnerID ",
"AND PrizeID = " + prize.ID
);
connection.Open();
OleDbCommand command = new OleDbCommand(query, connection);
OleDbDataReader reader = command.ExecuteReader();
...
connection.Close();
}
return winners;
}
method2
public static List<string> GetDoubles(Prize prize)
{
List<string> doubles = new List<string>();
using (OleDbConnection connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["ForteLotteryDataConnectionString"].ConnectionString))
{
var query = string.Concat(
#"
SELECT Member.IBAN ",
"FROM Member, Summary ",
"WHERE Member.ID = Summary.DoubleID ",
"AND PrizeID = " + prize.ID
);
connection.Open();
OleDbCommand command = new OleDbCommand(query, connection);
OleDbDataReader reader = command.ExecuteReader();
...
connection.Close();
}
return doubles;
}
Use String.Format and pass the propname as a param:
public static List<string> GetSomething(string propName, Prize prize)
{
List<string> doubles = new List<string>();
using (OleDbConnection connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["ForteLotteryDataConnectionString"].ConnectionString))
{
var query = string.Format(
#"SELECT Member.IBAN,
FROM Member, Summary,
WHERE Member.ID = Summary.{0},
AND PrizeID = {1}", propName, prize.ID
);
connection.Open();
OleDbCommand command = new OleDbCommand(query, connection);
OleDbDataReader reader = command.ExecuteReader();
...
connection.Close();
}
return doubles;
}
BTW - be carefull from SQLI's - Read about parameterized queries.
Well, you could pass the type that you want as an enum, and read it.
It'll look like so:
enum Target { DOUBLES, WINNERS } // add as many as you want.
public static List<string> GetTarget(Prize prize, Target lookingFor)
{
....
// define the query
switch(lookingFor) // take care of each case in the enum.
{
case Target.DOUBLES:
query = string.Concat(
#"
SELECT Member.IBAN ",
"FROM Member, Summary ",
"WHERE Member.ID = Summary.DoubleID ",
"AND PrizeID = " + prize.ID
);
break;
case Target.WINNERS:
query = string.Concat(
#"
SELECT Member.IBAN ",
"FROM Member, Summary ",
"WHERE Member.ID = Summary.WinnerID ",
"AND PrizeID = " + prize.ID
);
break;
default: // in case you got a bad value
//throw an exception
break;
}
//Do stuff with the query.
}
Method 1
public static List<string> GetWinners(Prize prize)
{
List<string> winners = new List<string>();
using (OleDbConnection connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["ForteLotteryDataConnectionString"].ConnectionString))
{
var query = string.Concat(
#"
SELECT Member.IBAN ",
"FROM Member, Summary ",
"WHERE Member.ID = Summary.WinnerID ",
"AND PrizeID = " + prize.ID
);
connection.Open();
OleDbCommand command = new OleDbCommand(query, connection);
OleDbDataReader reader = command.ExecuteReader();
...
connection.Close();
}
return winners;
}
Method2
public static List<string> GetDoubles(Prize prize)
{
List<string> doubles = new List<string>();
using (OleDbConnection connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["ForteLotteryDataConnectionString"].ConnectionString))
{
var query = string.Concat(
#"
SELECT Member.IBAN ",
"FROM Member, Summary ",
"WHERE Member.ID = Summary.DoubleID ",
"AND PrizeID = " + prize.ID
);
connection.Open();
OleDbCommand command = new OleDbCommand(query, connection);
OleDbDataReader reader = command.ExecuteReader();
...
connection.Close();
}
return doubles;
}
Joining these methods
protected void JoinMethods()
{
List<string> j = new List<string>();
j.AddRange(this.GetWinners("Parameters goes here"); //Method 2
j.AddRange(this.GetDoubles("Parameters goes here"); //Method 2
}
I'd rather enumerate possible cases (enum WinnerKind), something like that:
public enum WinnerKind {
Winner = 0,
Double = 1
}
...
public static List<string> GetWinnersData(Prize prize, WinnerKind kind) {
List<string> result = new List<string>();
// You don't have to concat strings
// it's a good practice to use parametrized queries: "PrizeID = ?"
String query = String.Format(
#"SELECT Member.IBAN,
FROM Member,
Summary,
WHERE Member.ID = {0}
AND PrizeID = ?",
kind == WinnerKind.Winner ? "Summary.WinnerID" : "Summary.DoubleID");
using (OleDbConnection connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["ForteLotteryDataConnectionString"].ConnectionString)) {
connection.Open();
using (OleDbCommand command = new OleDbCommand(query, connection)) {
// named parameters aren't supported
command.Parameters.Add(prize.ID);
using (OleDbDataReader reader = command.ExecuteReader()) {
while (reader.Read())
result.Add(Convert.ToString(reader[0].GetValue()));
}
}
}
return result;
}
public static List<string> GetWinners(Prize prize) {
return GetWinnersData(prize, WinnerKind.Winner);
}
public static List<string> GetDoubles(Prize prize) {
return GetWinnersData(prize, WinnerKind.Double);
}

How can i log SqlCommand queries to analyze at SQL server tuning advisor

I have a DB connection class which executes all of my DB connections
I want to capture the queries and run them on SQL server tuning advisor to find out missing indexes etc
The SQL server profiler tuning takes forever to process. So i want to compose my own file to analyze
The issue is i don't know how should i capture query to properly analyze
Here my SqlCommand function
SQL server 2014 , c# .net 4.5
My question is what parameters, values etc i should log to analyze them perfectly
public static DataTable cmd_SelectQuery(string srCommandText, List<string> lstParameterNames, List<object> lstParameters)
{
DataTable dsCmdPara = new DataTable();
try
{
using (SqlConnection connection = new SqlConnection(DbConnection.srConnectionString))
{
using (SqlCommand cmd = new SqlCommand(srCommandText, connection))
{
cmd.CommandTimeout = PublicSettings.irCommandTimeOutSettings_Second;
cmd.CommandType = CommandType.Text;
object objParameter;
for (int i = 0; i < lstParameterNames.Count; i++)
{
objParameter = lstParameters[i];
if (objParameter == null)
objParameter = "n";
cmd.Parameters.AddWithValue(lstParameterNames[i], lstParameters[i].ToString());
}
using (SqlDataAdapter sqlDa = new SqlDataAdapter(cmd))
{
sqlDa.Fill(dsCmdPara);
return dsCmdPara;
}
}
}
}
catch (Exception E)
{
Interlocked.Increment(ref GlobalStats.long_GlobalSQLErrorCount);
StringBuilder srParameters = new StringBuilder();
if (PublicSettings.blLogSqlParametersOnErrors == true)
{
srParameters.AppendLine("");
srParameters.AppendLine("error at : cmd_UpdateDeleteQuery");
foreach (var vrItem in lstParameters)
{
srParameters.AppendLine("per parameter: " + vrItem + " \r\n\r\n");
}
}
if (PublicSettings.blLogSqlErrors)
ErrorLogger.LogSQL_Error("Error at: cmd_SelectQuery " + srCommandText + " " + E.Message.ToString() + " \r\n" + srParameters.ToString());
}
return dsCmdPara;
}
public static bool cmd_UpdateDeleteQuery(string srCommandText, List<string> lstParameterNames, List<object> lstParameters)
{
try
{
using (SqlConnection connection = new SqlConnection(DbConnection.srConnectionString))
{
using (SqlCommand cmd = new SqlCommand(srCommandText, connection))
{
cmd.CommandTimeout = PublicSettings.irCommandTimeOutSettings_Second;
cmd.CommandType = CommandType.Text;
object objParameter;
for (int i = 0; i < lstParameterNames.Count; i++)
{
objParameter = lstParameters[i];
if (objParameter == null)
objParameter = "n";
cmd.Parameters.AddWithValue(lstParameterNames[i], objParameter);
}
connection.Open();
cmd.ExecuteNonQuery();
return true;
}
}
}
catch (Exception E)
{
Interlocked.Increment(ref GlobalStats.long_GlobalSQLErrorCount);
StringBuilder srParameters = new StringBuilder();
if (PublicSettings.blLogSqlParametersOnErrors == true)
{
srParameters.AppendLine("");
srParameters.AppendLine("error at : cmd_UpdateDeleteQuery");
foreach (var vrItem in lstParameters)
{
srParameters.AppendLine("per parameter: " + vrItem + " \r\n\r\n");
}
}
if (PublicSettings.blLogSqlErrors)
ErrorLogger.LogSQL_Error("Error at: cmd_UpdateDeleteQuery " + srCommandText + " " + E.Message.ToString() + srParameters.ToString());
}
return false;
}

How to retrieve all fields for a given record using OracleDataReader?

My question, which is similar to this one, is how can I use OracleDataReader to retrieve all the fields for a given record? Currently, I've been using this method, which returns only one column value at a time:
public string Select_File(string filename, string subdirectory, string envID)
{
Data_Access da = new Data_Access();
OracleConnection conn = da.openDB();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename ='" + filename + "'"
+ " AND Subdirectory = '" + subdirectory + "'"
+ " AND Environment_ID = '" + envID + "'";
cmd.CommandType = CommandType.Text;
string x;
OracleDataReader dr = cmd.ExecuteReader();
if (dr.HasRows) // file exists in DB
{
dr.Read();
x = dr.GetString(2).ToString(); // return baseline filename (index 2)
}
else
{
x = "New File";
}
cmd.Dispose();
da.CloseDB(conn);
return x;
}
I'm sure that this method is far from perfect and ppl will be quick to point that out (I was basically given it by my supervisor since I didn't have any prior experience in ASP.NET) but all I really care about is that it works. My question is: how can it be modified to return all the fields for a given record?
The fields will be of either VARCHAR2, CHAR, or DATE datatypes, (if that makes a difference) and some of these values may be null. I'm thinking I could convert them to strings and return them as a list?
if u want something like this:
List<User> lstUser = new List<User>();
string sqlQuery = "Select * from User_T where User_Name='" + oUser.UserName + "' And Password='" +oUser.Password + "' AND IsActive='"+1+"' AND IsDelete='"+0+"'";
string connectionString = "Data Source=ORCL;User Id=ACCOUNTS;Password=ACCOUNTS";
using (DBManager dbManager = new DBManager(connectionString))
{
try
{
dbManager.Open();
OracleDataReader dataReader = dbManager.ExecuteDataReader(sqlQuery);
while (dataReader.Read())
{
oUser = new User();
oUser.Id = Convert.ToInt32(dataReader["ID"]);
oUser.CompanyId = Convert.ToInt32(dataReader["Company_ID"]);
oUser.BranchId = Convert.ToInt32(dataReader["Branch_ID"]);
oUser.UserName = Convert.ToString(dataReader["User_Name"]);
lstUser.Add(oUser);
}
dataReader.Close();
dataReader.Dispose();
}
catch
(Exception)
{
}
finally
{
dbManager.Close();
dbManager.Dispose();
}
To read all the data from the columns of the current row in a DataReader, you can simply use GetValues(), and extract the values from the array - they will be Objects, of database types.
Object[] values;
int numColumns = dr.GetValues(values); //after "reading" a row
for (int i = 0; i < numColumns; i++) {
//read values[i]
}
MSDN - "For most applications, the GetValues method provides an efficient means for retrieving all columns, rather than retrieving each column individually."
Sorry for posting an answer to a very old question. As none of the answers are correct (either they have security issues or not checking for DBNull), I have decided to post my own.
public async Task<StringBuilder> FetchFileDetailsAsync(string filename, string subdirectory, string envId)
{
var sb = new StringBuilder();
//TODO: Check the parameters
const string connectionString = "user id=userid;password=secret;data source=" +
"(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.0.0.8)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=xe)))";
const string selectQuery = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename = :filename"
+ " AND Subdirectory = :subdirectory"
+ " AND Environment_ID = :envID"
+ " AND rownum<=1";
using (var connection = new OracleConnection(connectionString))
using (var cmd = new OracleCommand(selectQuery, connection) {BindByName = true, FetchSize = 1 /*As we are expecting only one record*/})
{
cmd.Parameters.Add(":filename", OracleDbType.Varchar2).Value = filename;
cmd.Parameters.Add(":subdirectory", OracleDbType.Varchar2).Value = subdirectory;
cmd.Parameters.Add(":envID", OracleDbType.Varchar2).Value = envId;
//TODO: Add Exception Handling
await connection.OpenAsync();
var dataReader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection);
var rowValues = new object[dataReader.FieldCount];
if (dataReader.Read())
{
dataReader.GetValues(rowValues);
for (var keyValueCounter = 0; keyValueCounter < rowValues.Length; keyValueCounter++)
{
sb.AppendFormat("{0}:{1}", dataReader.GetName(keyValueCounter),
rowValues[keyValueCounter] is DBNull ? string.Empty : rowValues[keyValueCounter])
.AppendLine();
}
}
else
{
//No records found, do something here
}
dataReader.Close();
dataReader.Dispose();
}
return sb;
}

Categories

Resources