I got two standard projects in a solution. The UI and the Logic.
As usual, you need to take the inputs from the UI and do whatever you want with them in the back end part.
So in the UI class, I have this
private void btnAddItems_Click(object sender, RoutedEventArgs e)
{
item_name = lbl_item_name.Text;
item_quantity = lbl_item_quantity.Text;
store_ime = store_Name.Text;
logika.storeInDb(store_ime, item_name, item_quantity);
}
It just stores the input in variables and then sends them to this
public void storeInDb(string store_name, string item_name, string item_quantity)
{
using (MySqlConnection mySqlConn = new MySqlConnection(Logic.connStr))
{
dbInsert($"INSERT INTO soping(store_name, item_name, item_quantity, payment_type, date) VALUES('{store_name}', '{item_name}', '{item_quantity}', 'visa', 'danas')");
}
}
And this is the dbInsert method
public void dbInsert(string query)
{
using (MySqlConnection mySqlConn = new MySqlConnection(Logic.connStr))
{
try
{
mySqlConn.Open();
MySqlCommand cmd = new MySqlCommand(query, mySqlConn);
cmd.ExecuteNonQuery();
mySqlConn.Close();
}
catch (MySqlException e)
{
System.Diagnostics.Debug.WriteLine(e);
}
}
}
It doesn't store anything. And when I use breakpoints, it seems like the button method runs after storeInDb, even though the variables in the query are perfectly fine. And I can't find anything wrong with the code that would make it behave weird like this.
This code have some issues:
1- You should use parameters instead of direct strings in your sql query;
2- You don't need a connection outside your dbInsert Method
However, this code should work. I guess the problem you are having is located elsewhere, not in the code you posted here. Something simpler, maybe connectionstring problem (saving in other place where you don't expect to) or bad uses of threads...Maybe hitting deadlocks, long processing or something like that (the only way i can think of having button click apparently happenning after the code it calls).
Related
I'm trying to return a string though a Getter, the string is obtained from a DataRead object which loops through the mysql query. The problem is that, upon load, the string does not get loaded onto the main form's label, it returns an empty string and if I assign a string to the variable upon declaration, it returns that to my main form. Here's the code:
string text;
public string Text { get { return text; } }
public void DBConn()
{
MySqlConnection conn = new MySqlConnection(connStr);
DataSet ds = new DataSet();
MySqlDataReader reader = null;
try
{
// connection to DB
reader = cmd.ExecuteReader();
if (reader != null && reader.HasRows)
{
while (reader.Read())
{
text = reader["string1"].ToString() + " " + reader["string2"].ToString() + " " + reader["string3"].ToString();
}
}
}
// try, catch. conn.close()
}
The reader is assigning the values onto text just fine, but outside of the while, the value is not assigned to the globally declared variable, it seems to get destroyed as soon as it leaves the loop. Can anyone please help?
Thank you.
Thank you to those who helped me find the solution to the problem described. As some of you kindly explained (and I was lacking the knowledge to understand at first until a lot of research was done), the issue turned out to be a problem with my Main form being in a different instance from the first class that calls upon the class that has the Getter in it. I know now I should have mentioned all of these details in the original post, I apologize to those of you who tried to understand from a small piece of code. After a lot of research on Instances, the solution I came to was to first, create a class that holds static Getters and Setters public static string Text { set; get; } (this was how I wanted it for easy access from other classes) this helps in making them accessible from all instances, it might not be the best solution especially on OOP - During my research I read somewhere that using Setters and Getters is a waste of time and not the best practice for programmers, that it is best to encapsulate but because I am still very fresh I will look up how to do that later.
Thank you guys again.
Hi I'm writing a program that IO from databses and I have the following function to read from the database and adds the rows to a combobox:
private void loadFromTuzel()
{
string constring = "Server=localhost;Database=ozturk;Uid=____;pwd=_____";
MySqlConnection newCon = new MySqlConnection(constring);
string selectCommand = "SELECT * FROM ozturk.tuzelkisi";
MySqlCommand cmd = new MySqlCommand(selectCommand, newCon);
MySqlDataReader myReader;
newCon.Open();
myReader = cmd.ExecuteReader();
while (myReader.Read())
{
cbselected.Items.Add(myReader["name"].ToString() + " " + myReader["Surname"].ToString());
}
}
as can be seen from the code the program loads the data from database to the combobox...
I need to use this function in a different form but need to load the data to a different combo box and I'm wondering if adding a toolbox item as a parameter to my function is possible so that it would be something like this
private void myfunction(thecombobox parameter comes here)
{
// The execution code and than
// thecomboboxparameter.items.add......
}
so I can use this function over and over at different forms just by adding the parameter value, is something like this possible?
Thanks
Yes, it is possible, but you'd be much better suited by moving that logic outside of your UI code altogether, and just return the items from the database. Don't pass the ComboBox to a parameter, but get the results from that method, and in your UI then tie everything together.
This is the basis of Separation of Concerns. Your ComboBoxes shouldn't care where the data comes from. They only care that they have data to display.
For the simple answer to your question, just adjust your method like this:
public static class Utilities
{
public static void loadFromTuzel(ComboBox cbo)
{
/// All of you other logic
while (myReader.Read())
{
cbo.Items.Add(myReader["name"].ToString() + " " +
myReader["Surname"].ToString());
}
}
}
If you follow SoC, then you'd have something like this:
public class Repository {
public IEnumerable<string> GetNamesFromTuzel()
{
// All of the same logic
while (myReader.Read())
{
yield return myReader["name"].ToString() + " " +
myReader["Surname"].ToString();
}
}
}
I have this code that queries a database. I want to put the actual database code into a separate class so I can reuse it in other places. This will leave just the actual read of the PassResult value so I can make a Unit Test of the code without having the SQL code running. I am having trouble finding references on how to make this kind of code Unit Testable. Could someone help out?
using System;
using System.Data;
using System.Data.SqlClient;
namespace CS_UI_Final_Inspection
{
public class CalibrationTestCheck
{
// declare the variables
private bool _calibrationTestPass = false;
private string _connectionString = string.Empty;
public bool CheckCalibrationTestResults(string serialNumber, IDeviceInfo deviceInfo, string mapID)
{
// get database location
DhrLocationPull dhrLocation = new DhrLocationPull();
_connectionString = dhrLocation.PullDhrLocation();
// build the query
SqlConnection calibrationCheckConnection = new SqlConnection(_connectionString);
SqlCommand calibrationCheckCommand = new SqlCommand("[MfgFloor].[GetLatestTestResultsForDeviceByTestType]",
calibrationCheckConnection);
// build the stored proc
calibrationCheckCommand.CommandType = CommandType.StoredProcedure;
calibrationCheckCommand.Parameters.Add(new SqlParameter("#SerialNumber", serialNumber));
calibrationCheckCommand.Parameters.Add(new SqlParameter("#DeviceTypeID", mapID));
calibrationCheckCommand.Parameters.Add(new SqlParameter("#TestDataMapTypeID", "C"));
calibrationCheckCommand.Connection.Open();
SqlDataReader calibrationCheckReader = calibrationCheckCommand.ExecuteReader();
// is there data?
if (calibrationCheckReader.HasRows)
{
// read the data
calibrationCheckReader.Read();
try
{
_calibrationTestPass = (bool) calibrationCheckReader["PassResult"];
}
catch (InvalidOperationException)
{
// means last element was not filled in
}
finally
{
// close refs
calibrationCheckReader.Close();
calibrationCheckCommand.Connection.Close();
calibrationCheckConnection.Close();
calibrationCheckReader.Dispose();
calibrationCheckCommand.Dispose();
calibrationCheckConnection.Dispose();
}
}
return _calibrationTestPass;
}
}
}
create an interface and implement it.
move all references to be tested to use the interface (exposing any methods/properties required through the interface)
have the constructor or method being tested take the interface as a parameter.
Roy Oscherov is a good resource on this. Roy Oscherov wrote a great book called "The art of unit testing". Roy's website can be found here: http://osherove.com/
I know what I asking might not make a lot of sense for C# experts but I'll explain what I want to do and then you can suggest me how to do it in a better way if you want ok?
I have a C# class called DatabaseManager that deals with different MySQL queries (ado.net NET connector, not linq or any kind of ActiveRecord-ish library).
I am doing something like
categories = db_manager.getCategories();
The list of categories is quite small (10 items) so I'd like to know what's the best way of accessing the retrieved information without a lot of additional code.
Right now I'm using a Struct to store the information but I'm sure there's a better way of doing this.
Here's my code:
public struct Category
{
public string name;
}
internal ArrayList getCategories()
{
ArrayList categories = new ArrayList();
MySqlDataReader reader;
Category category_info;
try
{
conn.Open();
reader = category_query.ExecuteReader();
while (reader.Read())
{
category_info = new Category();
category_info.name = reader["name"].ToString();
categories.Add(category_info);
}
reader.Close();
conn.Close();
}
catch (MySqlException e)
{
Console.WriteLine("ERROR " + e.ToString());
}
return categories;
}
Example:
public IEnumerable<Category> GetCategories()
{
using (var connection = new MySqlConnection("CONNECTION STRING"))
using (var command = new MySqlCommand("SELECT name FROM categories", connection))
{
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
yield return new Category { name = reader.GetString(0) };
}
}
}
}
Remarks:
Let ADO.NET connection pooling do the right work for you (avoid storing connections in static fields, etc...)
Always make sure to properly dispose unmanaged resources (using "using" in C#)
Always return the lowest interface in the hierarchy from your public methods (in this case IEnumerable<Category>).
Leave the callers handle exceptions and logging. These are crosscutting concerns and should not be mixed with your DB access code.
The first thing I would do is to replace you use of ArrayList with List that will provide compile-time type checkig for your use of the category list (so you will not have to type cast it when using it in your code).
There's nothing wrong with returning them in an like this. However, a few things stand out:
Your catch block logs the error but
then returns either an empty array or
a partially populated array. This
probably isn't a good idea
If an exception is thrown in the try
block you won't close the connection
or dispose of the reader. Consider
the using() statement.
You should use the generic types
(List<>) instead of ArrayList.
From your code I guess you are using .NET 1.1, becuase you are not using the power of generics.
1) Using a struct that only contains a string is an overkill. Just create an arraylist of strings (or with generics a List )
2) When an exception occurs in your try block, you leave your connection and reader open... Use this instead:
try
{
conn.open();
//more code
}
catch (MySqlException e) { // code
}
finally {
conn.close()
if (reader != null)
reader.close();
}
I've got a SqlServer project with a very simple test for a Table-Valued-Function:-
[SqlFunction(TableDefinition = "forename nvarchar(50)", FillRowMethodName = "TestFillRow", DataAccess = DataAccessKind.Read)]
public static IEnumerable TestConn(int ID)
{
using (SqlConnection con = new SqlConnection("context connection=true"))
{
//con.Open();
yield return "Anthony";
}
}
public static void TestFillRow(object obj, out string forename)
{
forename = (string)obj;
}
Note the Open on the connection is currently commented out. Once deployed I can execute like this in SQL:-
SELECT * FROM [dbo].[TestConn](1)
All works fine.
Now I uncomment the con.open() and it fails with:-
Data access is not allowed in this
context. Either the context is a
function or method not marked with
DataAccessKind.Read or
SystemDataAccessKind.Read, is a
callback to obtain data from FillRow
method of a Table Valued Function, or
is a UDT validation method.
I don't see what the problem is, the TestConn function has got DataAccessKind.Read.
Anyone know of any other reasons for getting this error?
The problem is the following:
SQLCLR does not allow any data access inside TestFillRow
Even though it "looks" like your TestFillRow doesnt access data, the way the compiler translates code with "yield" statements is by actually deferring it's execution until the first .MoveNext() call to the iterator. Therefore the following statement:
using (SqlConnection con = new SqlConnection("context connection=true"))
gets executed inside TestFillRow... which is illegal.
Do not use yield return; instead load the whole result to a List<> and return the list at the end of the UD Function.
"SQLCLR does not allow any data access inside TestFillRow" is a mistake.
If you don't use context connection = true connetion string you can access data inside FillRow method.