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);
}
Related
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 ";
[UPDATED]
I got a situation here where I need to fetch data from 2 different databases and then combine it into a model. I have an API method I made here that takes care of that but the moment I started working with a second database I got really confused on how I can retrieve more than one item. I'll explain. Here is the code to that method:
private List<FidelityModel> models;
public List<FidelityModel> getFidelityInfo2(string jobID) {
FidelityModel fidelityInfo;
SqlCommand command;
SqlConnection conn;
SqlDataReader reader;
string cjsJobName, ipwNumber, overnight, site;
int packageCount;
DateTime sla;
models = new List<FidelityModel>();
using (conn = new SqlConnection(#"server = [servername]; database = Dropoff; Integrated Security = true;")) {
conn.Open();
command = new SqlCommand("SELECT " +
"[Job Name], " +
"[Job ID], " +
"[Package Count], " +
"[Ship Method] " +
"FROM [cjs_data] " +
"WHERE [File Name] LIKE '%FDY%' AND [JOB ID] = #jobID", conn);
command.Parameters.Add("#jobID", SqlDbType.VarChar);
command.Parameters["#jobID"].Value = jobID;
//restructure to assign search results to string to later assign to model, as we will search again for SLA in a different database
using (reader = command.ExecuteReader()) {
if (reader.HasRows) {
while (reader.Read()) {
fidelityInfo = new FidelityModel();
fidelityInfo.cjsJobName = reader.GetString(0);
fidelityInfo.ipwNumber = reader.GetString(1);
fidelityInfo.packageCount = reader.GetInt32(2);
if (fidelityInfo.cjsJobName.Contains("OVN")) { fidelityInfo.overnight = "Yes"; } else {
fidelityInfo.overnight = (reader.GetString(3).Equals("Overnight")) ? "Yes" : "No";
}
//site = (cjsJobName.Contains("EDG")) ? "EDGEWOOD" : "Other Site"; //not always the case
fidelityInfo.site = "EDGEWOOD";
models.Add(fidelityInfo);
}
}
}
}
//How to incorporate this following block of code into the same model?
using (conn = new SqlConnection(#"server = [servername]; database = MustMail; Integrated Security = true;")) {
conn.Open();
command = new SqlCommand("SELECT [SLA] FROM [Job] WHERE [JobID] = #jobID", conn);
command.Parameters.Add("#jobID", SqlDbType.VarChar);
command.Parameters["#jobID"].Value = jobID;
using (reader = command.ExecuteReader()) {
if (reader.HasRows) {
while (reader.Read()) {
//fidelityInfo.sla = reader.GetDateTime(0);
}
}
}
}
return models;
}
As you can see right now I just have it working without fetching the SLA because I have no idea how to actually add the result I am fetching from the second database to the same model.
For each row in the DataReader create a new FidelityModel and add it to the list. Something like:
while (reader.Read())
{
var m = new FidelityModel()
{
cjsJobName = reader.GetString(0),
ipwNumber = reader.GetString(1),
packageCount = reader.GetInt32(2),
sla = DateTime.Now
};
if (m.cjsJobName.Contains("OVN"))
{
m.overnight = "Yes";
}
else
{
m.overnight = (reader.GetString(3).Equals("Overnight")) ? "Yes" : "No";
}
models.Add(m);
}
I want to retrive data from two differentables in my mysql data base so i created one connection and two readers, The second reader is not returning any results but the first reader is.
public List<BlogContentItemClass> BCITLIST = new List<BlogContentItemClass>();
// GET: api/BlogContents
[HttpGet]
public List<BlogContentItemClass> Get(string id)
{
string sqlstring = "server=; port= ; user id =;Password=;Database=;";
MySqlConnection conn = new MySqlConnection(sqlstring);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
string Query = "SELECT * FROM test.blogtable where `id` = '" + id + "' ";
MySqlCommand cmd = new MySqlCommand(Query, conn);
MySqlDataReader MSQLRD = cmd.ExecuteReader();
BlogContentItemClass BCIT = new BlogContentItemClass();
Label BLOGID = new Label();
if (MSQLRD.HasRows)
{
while (MSQLRD.Read())
{
string TC = (MSQLRD["Topic"].ToString());
string CT = (MSQLRD["Category"].ToString());
string SM = (MSQLRD["Summary"].ToString());
string BID = (MSQLRD["id"].ToString());
BCIT.TopicSaved1 = TC;
BCIT.CategoriesSaved1 = CT;
BCIT.SummarySaved1 = SM;
BLOGID.Text = BID;
BCIT.TotalBodyStackLayout1.Add("Hello");
}
}
BCITLIST.Add(BCIT);
MSQLRD.Close();
string Query1 = "SELECT * FROM test.blogbodytable where `BlogID` = '" + BLOGID.Text + "' ";
MySqlCommand cmd1 = new MySqlCommand(Query1, conn);
MySqlDataReader MSQLRD1 = cmd1.ExecuteReader();
if (MSQLRD1.HasRows)
{
while (MSQLRD1.Read())
{
string BLOGBODY ;
BLOGBODY = (MSQLRD1["BlogBody"].ToString());
BCIT.TotalBodyStackLayout1.Add(BLOGBODY);
}
}
BCITLIST.Add(BCIT);
conn.Close();
return BCITLIST;
}
from my code the line BCIT.TotalBodyStackLayout1.Add("Hello"); in the first reader does add "hello" to the BCIT.TotalBodyStacklayout1, but the line BCIT.TotalBodyStackLayout1.Add( BLOGBODY); does not work, what am i doing wrong?
Can you be more specific what you mean by 'BCIT.TotalBodyStackLayout1.Add(BLOGBODY);' does not work. Are you getting any exception? or if BLOGBODY coming empty? There are few primitive troubleshooting steps you can perform to nail-down the issue
confirm what BLOGID.Text you are getting from your previous query and corresponding data is available in test.blogbodytable for that id.
if (MSQLRD1.HasRows) is resolving to true
Were you able to get inside while (MSQLRD1.Read())
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;
}
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;
}