i want to return a string "Passed"From method Return Class Maintain, when the test passes,
And string "Failed" when the Test fails,
What I am attempting to do is make public static void Return_Pass() more dynamic and write it once instead of writing it multiple times, by passing Passed or Failed int the T-SQL statment in the method
public static void Return_Pass()
public class MainTain
{
public static void Return()
{
try
{
Thread.Sleep(5000);
Database.Return();
var icon = Browser.Driver.FindElement(By.XPath("//label[contains(text(), 'Search:')]"));
icon.SendKeys("TEST8");
Thread.Sleep(1000);
Browser.Driver.FindElement(By.XPath("//button[#title='Edit user']")).Click();
Thread.Sleep(500);
Browser.Driver.FindElement(By.XPath("//button[.= 'Return']")).Click();
Thread.Sleep(500);
Maint_Tests_Pass.Return_Pass();
Console.WriteLine(P);
}
catch (Exception e)
{
Browser.Closed();
Maint_Tests_Fail.Return_Fail();
Environment.Exit(-1);
}
}
}
To method Return_Pass Class Maint_Tests_pass
public class Maint_Tests_Pass
{
public static void Return_Pass()
{
string connetionString;
SqlConnection cnn;
connetionString = "Server=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=\"C:\\Users\\marco zani\\Documents\\marco.mdf\";Integrated Security=True;Connect Timeout=30";
cnn = new SqlConnection(connetionString);
SqlCommand command;
string sql = "INSERT INTO TestRun (Date,Message) VALUES (GETDATE(),'Test Return Passed')";
command = new SqlCommand(sql, cnn);
cnn.Open();
command.ExecuteReader();
cnn.Close();
cnn.Dispose();
}
}
i am fairly new to C# any help is appreciated..
method return_pass now
public static void Return_Pass(bool pass, string test)
{
string connetionString;
SqlConnection cnn;
connetionString = "Server=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=\"C:\\Users\\marco zani\\Documents\\marco.mdf\";Integrated Security=True;Connect Timeout=30";
cnn = new SqlConnection(connetionString);
SqlCommand command;
string passValue = pass ? "Passed" : "Failed";
string testreturn = test;
string sql = $"INSERT INTO TestRun (Date,Message) VALUES (GETDATE(),'{test} {passValue}')";
//string sql = "INSERT INTO TestRun (Date,Message) VALUES (GETDATE(),'Test Return Passed')";
command = new SqlCommand(sql, cnn);
cnn.Open();
command.ExecuteReader();
cnn.Close();
cnn.Dispose();
}
return method now
public static void Return()
{
try
{
Thread.Sleep(5000);
Database.Return();
var icon = Browser.Driver.FindElement(By.XPath("//label[contains(text(), 'Search:')]"));
icon.SendKeys("TEST8");
Thread.Sleep(1000);
Browser.Driver.FindElement(By.XPath("//button[#title='Edit user']")).Click();
Thread.Sleep(500);
Browser.Driver.FindElement(By.XPath("//button[.= 'Return']")).Click();
Thread.Sleep(500);
Maint_Tests_Pass.Return_Pass(true,"Test Return");
}
catch (Exception e)
{
Browser.Closed();
Maint_Tests_Pass.Return_Pass(false, "Test Return");
Environment.Exit(-1);
}
}
Rather than having two separate functions, have one that takes a boolean and inserts the appropriate record.
public static void Record(bool passed)
{
string connetionString;
SqlConnection cnn;
connetionString = "Server=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=\"C:\\Users\\marco zani\\Documents\\marco.mdf\";Integrated Security=True;Connect Timeout=30";
cnn = new SqlConnection(connetionString);
SqlCommand command;
string sql = $"INSERT INTO TestRun (Date,Message) VALUES (GETDATE(),'Test Return {(passed ? "Passed" : "Failed"}')";
command = new SqlCommand(sql, cnn);
cnn.Open();
command.ExecuteReader();
cnn.Close();
cnn.Dispose();
}
And call thusly:
try
{
// as before
Maint_Tests_Pass.Record(true);
}
catch(Exception ex)
{
Maint_Tests_Pass.Record(false);
}
Now, it's beyond the scope of both your question and this answer, but when you've got this working, how about looking at parameterised SQL queries:
https://www.completecsharptutorial.com/ado-net/insert-records-using-simple-and-parameterized-query-c-sql.php
Have fun!
use string instead of void
then return your value
public static string Return_Pass()
{
...
return "yourvalue";
}
Based on my understanding of the question
public static void Return_Pass(bool pass)
{
// ...
// ...
string passValue = pass ? "Passed" : "Failed";
string sql = $"INSERT INTO TestRun (Date,Message) VALUES (GETDATE(),'Test Return {passValue}')";
// ...
// ...
}
Related
I placed my DB reader in a separate class file because I didn't want to keep rewriting it but I keep getting the error:
Object reference not set to an instance of an object. db was null
This is my DataReader:
namespace ProjectName
{
public class DBReader
{
string dsn = ConfigurationManager.ConnectionStrings["database"].ConnectionString.ToString();
public SqlDataReader SqlReader(string sql, string retDebug = "")
{
try
{
SqlConnection conn;
SqlCommand cmd;
SqlDataReader dr_user;
conn = new SqlConnection(dsn);
conn.Open();
try
{
cmd = new SqlCommand(sql, conn);
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 180;
dr_user = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dr_user;
}
catch (SqlException ex)
{
retDebug = ex.Message;
return null;
}
conn.Close();
conn.Dispose();
}
catch (Exception ex)
{
retDebug = ex.Message;
}
return null;
}
}
}
This is where I'm catching the error...at
SqlDataReader reader = db.SqlReader(query, "");
in the code shown here:
<!DOCTYPE html>
<script runat="server">
ProjectName.DBReader db;
string projectName;
protected void Page_Load(object sender, EventArgs e)
{
LoadProjects();
}
public void LoadProjects()
{
string query = #"SELECT * FROM projects where project_type = 3;
SqlDataReader reader = db.SqlReader(query, "");
while (reader.Read())
{
//code does something here
}
}
</script>
I want to be able to reuse this because I know I will be using it many times in this project.
Any help/direction would be appreciated!
As others pointed out, like any class, you have to create a instance of that class before using.
HOWEVER, if you don't have any public vars (at least ones that will change with different users on the web site), then you can also have public members of that class, and create the class as static. (but, those public members MUST be the same for all logged on users)
So, your choice.
Always create an instance of the class before using.
eg this:
public void LoadProjects()
{
string query = #"SELECT * FROM projects where project_type = 3";
DBReader MyDB = new DBReader();
SqlDataReader reader = MyDB.SqlReader(query, "");
while (reader.Read())
{
//code does something here
}
}
Or, you can declare the class as static, like this:
(air code warning).
public static class DBReader
{
static readonly string dsn = ConfigurationManager.ConnectionStrings["database"].ConnectionString.ToString();
static public SqlDataReader SqlReader(string sql, string retDebug = "")
{
SqlDataReader dr_user = null;
using (SqlConnection conn = new SqlConnection(dsn))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 180;
conn.Open();
dr_user = cmd.ExecuteReader();
}
}
return dr_user;
}
}
So, now in code you don't have to create a instance.
eg:
public void LoadProjects()
{
string query = #"SELECT * FROM projects where project_type = 3";
SqlDataReader reader = MyCode.DBReader.SqlReader(query, "");
while (reader.Read())
{
//code does something here
}
}
I have a Class that processes DB column metadata. One of the Properties of the Class is the table in question. This is passed to the object via the constructor. Also in the constructor I apply some logic to assign other variables within the class. To do this there are a number of private methods that connect to a DB, query something about the table, and return a value to the variable.
My problem is that I have a lot of different methods doing pretty much the same thing, but returning a different datatype. So for example my code is something like this
public Column(string tableName)
{
strTableName = tableName;
pkColumnName = GetPKColumnName(tableName);
pkColumnLenght = GetPKColumnLenght(tableName);
}
private string GetPKColumnName(string tableName)
{
string query = String.Format("SELECT myColName FROM myTable where myTableName = {0}", tableName);
string result = "";
try
{
using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString))
{
con.Open();
using (SqlCommand command = new SqlCommand(query, con))
{
result = (string)command.ExecuteScalar();
}
}
}
catch (SqlException ex)
{
Console.WriteLine(ex.Message);
}
return result;
}
private int GetPKColumnLenght(string tableName)
{
string query = String.Format("SELECT myColLenght FROM myTable where myTableName = {0}", tableName);
int result = 0;
try
{
using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString))
{
con.Open();
using (SqlCommand command = new SqlCommand(query, con))
{
result = (int)command.ExecuteScalar();
}
}
}
catch (SqlException ex)
{
Console.WriteLine(ex.Message);
}
return result;
}
There are many other methods like this also. This didn't look great to me, so I was wondering what the best practice was for something like this.
Should I just declare the return type as an object and do the datatype conversions when assigning the returned value to my variable?
My answer and the other assume different questions. It appears to me that you are trying to query a single value from a specific column and that you have to create a new method because the types are different. That said, I would personally just use a simple ORM solution and the other answer certainly is not wrong, just another abstraction.
You will want to use generics and cast to the generic.
I haven't tested this code, it is more of a guideline.
private T GetValue<T>(string tableName, colName)
{
string query = String.Format("SELECT {0} FROM myTable where myTableName = {1}", colName, tableName);
T result = default(T);
try
{
using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString))
{
con.Open();
using (SqlCommand command = new SqlCommand(query, con))
{
result = (T)command.ExecuteScalar();
}
}
}
catch (SqlException ex)
{
Console.WriteLine(ex.Message);
}
return result;
}
Create SqlManager class
public class SqlManager
{
public static string ConnectionString
{
get
{
return "Your ConnectionString"
}
}
public static SqlConnection GetSqlConnection(SqlCommand cmd)
{
if (cmd.Connection == null)
{
SqlConnection conn = new SqlConnection(ConnectionString);
conn.Open();
cmd.Connection = conn;
return conn;
}
return cmd.Connection;
}
public static object ExecuteScalar(SqlCommand cmd)
{
SqlConnection conn = GetSqlConnection(cmd);
try
{
return cmd.ExecuteScalar();
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
}
Now your methods, for the second one same thing:
private string GetPKColumnName(string tableName)
{
string query = String.Format("", tableName);
SqlCommand cmd = new SqlCommand();
cmd.CommandText = #"SELECT myColName FROM myTable where myTableName = #TableName";
cmd.Parameters.AddWithValue("#TableName", tableName);
object result = SqlManager.ExecuteScalar(cmd);
return result != null ? (int)object: 0;
}
Trying to fill Combobox with data from a database and I'm using ExecuteReader as below, but when I try to instantiate my connection it shows me the error
Cannot implicitly convert type error
My DBConnect class code:
public class DBConnect
{
private SqlConnection connection;
private string servername = "10.1.76.109,1433";
private string database = "EngLib";
private string dbuser;
private string userpassword;
public DBConnect()
{
}
public void doDBConnect(string dbuserform, string userpasswordform)
{
dbuser = dbuserform;
userpassword = userpasswordform;
}
public void Initialize()
{
}
public bool openConnection()
{
string connectionString;
connectionString = "Server=" + servername + ";Database=" + database + ";user id=" + dbuser + ";Password=" + userpassword;
Console.WriteLine(connectionString);
connection = new SqlConnection(connectionString);
try
{
connection.Open();
return true;
}
catch (SqlException ex)
{
switch (ex.Number)
{
case 0:
MessageBox.Show("Não é possível contactar o servidor. Entre em contato com o administrador");
break;
case 18456:
MessageBox.Show("Usuário/Senha inválidos, tente novamente");
break;
}
return false;
}
}
My form code:
{
public Form2()
{
InitializeComponent();
}
public void Form2_Load(object sender, EventArgs e)
{
SqlDataReader rdr = null;
DBConnect sqlConnection;
sqlConnection = new DBConnect();
sqlConnection.doDBConnect(dbuserform: "usertest", userpasswordform: "usertest");
{
try
{
{
sqlConnection.openConnection();
SqlCommand sqlCmd;
sqlCmd = new SqlCommand("SELECT Material FROM EngLib");
sqlCmd.Connection = sqlConnection;
SqlDataReader sqlReader = sqlCmd.ExecuteReader();
while (sqlReader.Read())
{
comboBox1.Items.Add(sqlReader["Material"].ToString());
}
sqlReader.Close();
}
}
finally
{
// close the reader
if (rdr != null)
{
rdr.Close();
}
}
}
}
}
The user and password in the code is just temporary.
I think the problem is here:
DBConnect sqlConnection;
SqlCommand sqlCmd;
sqlCmd.Connection = sqlConnection;
SqlCommand expects that Connection is of type SqlConnection, but you are assigning your own class DBConnect.
Possible fixes:
Expose the connection property on DBConnect and use it.
Inherit DBConnect from SqlConnection.
Use SqlConnection directly.
An additional note: you are not disposing the SqlConnection inside your DBConnect class, which can lead to StackOverflowException. You should implement IDisposable.
I try to call function to select data from database,coz it will more efficient and i don't like to open connection and execute reader every time,have any solution can do like that?
this is my first method to select data from database,but will hit sql injection problem
protected void Button1_Click(object sender, EventArgs e)
{
Class1 myClass = new Class1();
lblAns.Text = myClass.getdata("Table1", "Student", "Student = '" + TextBox1.Text + "'");
}
public string getdata(string table,string field,string condition)
{
SqlDataReader rdr;
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True");
string sql = "select " + field + " from " + table + " where " + condition;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
return "true";
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Insert Error:";
msg += ex.Message;
}
finally
{
conn.Close();
}
return "false";
}
this is my second method but will hit error (ExecuteReader requires an open and available Connection. The connection's current state is closed.) at line (rdr = cmd.ExecuteReader();)
public string getdata(SqlCommand command,SqlConnection conn)
{
SqlDataReader rdr;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd = command;
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
return "true";
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Select Error:";
msg += ex.Message;
}
finally
{
conn.Close();
}
return "false";
}
public SqlConnection conn()
{
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True");
return conn;
}
protected void Button1_Click(object sender, EventArgs e)
{
Class1 myClass = new Class1();
string strSql;
strSql = "Select student from Table1 where student=#stu";
SqlCommand command = new SqlCommand(strSql, myClass.conn());
command.Parameters.AddWithValue("#stu", TextBox1.Text);
myClass.getdata(command, myClass.conn());
}
have solution can use 1st method but will not hit the sql injection problem?
Use ALWAYS the second solution. The only way to avoid Sql Injection is through the use of parameterized queries.
Also fix the error on the second example. You don't associate the connection to the command, also it is a bad practice to keep a global object for the connection. In ADO.NET exist the concept of Connection Pooling that avoid the costly open/close of the connection while maintaining a safe Handling of these objects
public string getdata(SqlCommand command)
{
// Using statement to be sure to dispose the connection
using(SqlConnection conn = new SqlConnection(connectionString))
{
try
{
conn.Open();
cmd.Connection = conn;
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
return "true";
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Select Error:";
msg += ex.Message;
return msg;
}
}
return "false";
}
This bit of code runs on Windows Compact Framework and what it does is obvious. It looks as it should be refactored (especially considering that I may want to add cmd.ExecuteResultSet() later), but I can't see an elegant way to do it. Any ideas appreciated.
internal void RunNonQuery(string query)
{
string connString = GetLocalConnectionString();
using (SqlCeConnection cn = new SqlCeConnection(connString))
{
cn.Open();
SqlCeCommand cmd = cn.CreateCommand();
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
}
internal int RunScalar(string query)
{
string connString = GetLocalConnectionString();
using (SqlCeConnection cn = new SqlCeConnection(connString))
{
cn.Open();
SqlCeCommand cmd = cn.CreateCommand();
cmd.CommandText = query;
return int.Parse(cmd.ExecuteScalar().ToString());
}
}
I'm not sure I would refactor it, but perhaps:
static void PerformQuery(string connectionString, string command,
Action<SqlCeCommand> action)
{ //TODO: sanity checks...
using(SqlCeConnection conn = new SqlCeConnection(connectionString))
using(SqlCeCommand cmd = conn.CreateCommand()) {
cmd.CommandText = command;
conn.Open();
action(cmd);
}
}
internal void RunNonQuery(string query)
{
string connString = GetLocalConnectionString();
PerformQuery(connString, query, cmd => cmd.ExecuteNonQuery());
}
internal int RunScalar(string query)
{
int result = 0;
string connString = GetLocalConnectionString();
PerformQuery(connString, query,
cmd => {result = int.Parse(cmd.ExecuteScalar().ToString()); }
);
return result;
}
Otherwise - just maybe a CreateAndOpenConnection(string) method, and a CreateCommand(SqlCeConnection,string) method.
If you are using C# 3.0, you could do something like the following:
private T CreateCommand<T>(string query, Func<SqlCeCommand, T> func)
{
var connString = GetLocalConnectionString();
using (var cn = new SqlCeConnection(connString))
{
cn.Open();
using (var cmd = cn.CreateCommand())
{
cmd.CommandText = query;
return func(cmd);
}
}
}
private void CreateCommand(string query, Action<SqlCeCommand> action)
{
CreateCommand<object>(query, cmd =>
{
action(cmd);
return null;
});
}
internal void RunNonQuery(string query)
{
CreateCommand(query, cmd => cmd.ExecuteNonQuery());
}
internal int RunScalar(string query)
{
return CreateCommand(query, cmd =>
int.Parse(cmd.ExecuteScalar().ToString()));
}
I would create a class out of the code to wrap the connection creation and command execution logic. This will provide you with a single place to implement transactions in the future and will consolidate creation of the connection and command. This consolidation will allow for settings timeouts, joining transactions, etc.
class Connection : IDisposable
{
readonly SqlConnection _conn;
public Connection()
{
string connString = GetLocalConnectionString();
_conn = new SqlConnection(connString);
_conn.Open();
}
public void Dispose() { _conn.Dispose(); }
public SqlCommand CreateCommand(string qry)
{
SqlCommand cmd = _conn.CreateCommand();
cmd.CommandText = qry;
//cmd.CommandTimeout = TimeSpan.FromMinutes(x);
return cmd;
}
public int ExecuteNonQuery(string qry)
{
using (SqlCommand cmd = CreateCommand(qry))
return cmd.ExecuteNonQuery();
}
public int RunScalar(string qry)
{
using (SqlCommand cmd = CreateCommand(qry))
return int.Parse(cmd.ExecuteScalar().ToString());
}
}
Then if you still want to maintain your original API, you do the following:
class SqlCode
{
internal void RunNonQuery(string query)
{
using (Connection cn = new Connection())
cn.ExecuteNonQuery(query);
}
internal int RunScalar(string query)
{
using (Connection cn = new Connection())
return cn.RunScalar(query);
}
}
The only thing left is to re-insert the 'Ce' in the SqlXxxx stuff ;)