I'm programming in C#. I'm trying to make a class, that when called will create a connection to the database.
My database connection class is here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
namespace HouseServer
{
class db
{
// Variable to hold the driver and location of database
public static OleDbConnection dbConnection;
// Database connection
public db()
{
// Define the Access Database driver and the filename of the database
dbConnection = new OleDbConnection("Provider=Microsoft.Ace.OLEDB.12.0; Persist Security Info = False; Data Source=Houses.accdb");
// Open the connection
dbConnection.Open();
}
}
}
And the main program is here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
namespace HouseServer
{
class Program : db
{
// List for holding loaded houses
static List<house> houses = new List<house>();
// Variable to hold "command" which is the query to be executed
private static OleDbCommand query;
// Variable to hold the data reader to manipulate data from the database
static OleDbDataReader dataReader;
static void Main(string[] args)
{
// Get the houses in a list
List<house> c = getHousesFromDb();
foreach (house yay in c)
{
// Show each house's full address
Console.WriteLine(yay.house_number + " " + yay.street);
Console.WriteLine(yay.house_town);
Console.WriteLine(yay.postcode);
}
// Readline to prevent window from closing
Console.ReadLine();
}
// Function which loads all of the houses from the database
private static List<house> getHousesFromDb()
{
// Define the query to be executed
query = new OleDbCommand("SELECT * FROM houses", dbConnection);
// Execute the query on the database and get the data
dataReader = query.ExecuteReader();
// Loop through each of the houses
while (dataReader.Read())
{
// Create a new house object for temporarily storing house
house house = new house();
// Create the house that we've just loaded
house.house_id = Convert.ToInt32(dataReader["house_id"]);
house.house_number = Convert.ToInt32(dataReader["house_number"]);
house.street = dataReader["house_street"].ToString();
house.house_town = dataReader["house_town"].ToString();
house.postcode = dataReader["house_postcode"].ToString();
// Now add the house to the list of houses
houses.Add(house);
}
// Return all of the houses in the database as a List<house>
return houses;
}
}
}
I thought that putting class Program : db would call the db constructor when the program opens, but when the code gets to the line dataReader = query.ExecuteReader();, it comes up with the error "ExecuteReader: Connection property has not been initialized.".
All I'm trying to achieve is a database connection within another class, that I can call and have available to all of my code.
Am I supposed to call the database class in a different way?
No, nothing's creating an instance of Program, and nothing's creating an instance of db. However, I'd strongly suggest you change your design completely:
Don't have a static field for your database connection. Open it when you need one, use it, close it. You should very rarely need to store it in anything other than a local variable.
Try not to use static variables at all if you can help it. They make your code harder to test, as they represent global state - that's harder to reason about than local state. In your program, I'd use local variables entirely.
Don't use inheritance for this sort of thing - your Program type doesn't logically derive from db
Follow .NET naming conventions for methods, classes and properties. Making your code "feel" like idiomatic C# will go a long way to making it more readable for other people.
This definately doesn't look right, your program should not inherit or extend your database class. Your database class is in its own right its own abstract data type. Your program should use the database class but not extend it.
I would change this up a bit by
Getting rid of the inheritance
Make the database class a static class (no reason to instantiate a database instance here)
Your program can then DBClass.GetData();
That is your program should use the database class as a black box, it definately should not inherit from it. It should use it without having the details of how it works. In your code:
// List for holding loaded houses
static List<house> houses = new List<house>();
// Variable to hold "command" which is the query to be executed
private static OleDbCommand query;
// Variable to hold the data reader to manipulate data from the database
static OleDbDataReader dataReader;
static void Main(string[] args)
{
// Get the houses in a list
List<house> c = getHousesFromDb();
You should hide the details of your OleDbCommand and OleDbDatareader objects, although its not required they could be managed elsewhere. Your getHousesFromDB should be called like:
MyDBClass.GetHousesFromDB()
Where MyDBClass is a static class that manages your database read / writes. The signature of GetHousesFromDB should return something to the effect of IList<House> GetHousesFromDB()
Though Jon Skeet & JonH make valid points, I'll answer why you're getting the exception. From there you should take their advice and redo this from scratch.
The reason you get the exception is that it is initialized in the constructor for db and it's never getting called.
If you add this line to Main, your program should work.
new Program();
But to reiterate: Take their advice and start over. In many settings, these toy projects quickly grow to full blown enterprise apps and once you get there, the mistakes made at the beginning stay there forever.
Related
When I try to search data in my user control from my database it does search or filter the data that I typed in the search textbox. Here's the code that I'm using to try and search or filter
SqlConnection cn;
SqlCommand cm;
SqlDataReader dr;
private Label name;
private Label amount;
private Label descrip;
public Form1()
{
InitializeComponent();
cn = new SqlConnection(#"Data Source=(LocalDB)");
}
private void Form1_Load(object sender, EventArgs e)
{
GetData();
}
private void GetData()
{
cn.Open();
cm = new SqlCommand("Select * from Bills where (billname) like '%" + txtSearch.Text + "%'", cn);
dr = cm.ExecuteReader();
while (dr.Read())
{
long len = dr.GetBytes(0, 0, null, 0, 0);
byte[] array = new byte[System.Convert.ToInt32(len) + 1];
dr.GetBytes(0, 0, array, 0, System.Convert.ToInt32(len));
name = new Label();
name.Text = dr["billname"].ToString();
descrip = new Label();
descrip.Text = dr["billdescrip"].ToString();
amount = new Label();
amount.Text = dr["billamount"].ToString();
}
dr.Close();
cn.Close();
}
private void txtSearch_TextChanged(object sender, EventArgs e)
{
GetData();
}
When I type something into the txtSearch.text box, the results come back empty and doesn't display the what im trying to search for in the txtSearch.text box.
"Select * from Bills where (billname) like '%" + txtSearch.Text + "%'"
It seems to me that you have a database table Bills, with a column BillName. The operator types some text in TextBox txtSearch, and you want to fetch all Bills that have a BillName that starts with the text in the TextBox.
I see several problems here
SQL Injection
SQL injection is a code injection technique that might destroy your database.
SQL injection is one of the most common web hacking techniques.
SQL injection is the placement of malicious code in SQL statements
Look what your Sql text would be if the operator types the following text:
"John%; DROP TABLE Bills;--"
Select * from Bills where (billname) like %John%; DROP TABLE Bills; --%
You would lose all Bills!
More information about SQL Injection
Solution: Never, ever add input data into your sql string! Always add it as a parameter!
Start using using statements
The database connection is a scarce resource: you should not keep it alive longer than needed. Also, if you SQL query encounters an exception, the connection and the datareader are not closed.
Make it a habit, that whenever an object implements IDisposable you should use it using a using statement.
This way, you can be assured that whatever happens, at the end of the using statement everything is properly flushed, written, closed and disposed.
SqlConnection, SqlCommand and SqlDataReader should be private members of GetData. This way you can be certain that no one can tamper with your connection; you hide how you fetch the data from the database (SQL and SqLCommand, or Entity Framework and LINQ?), thus making future changes easier. Readers of your code won't have to check where these variables are used, and that no one is misusing it, thus making your code easier to understand. And of course this will make it possible to reuse GetData for other purposes.
Which brings me to the third improvement:
Separate data from how it is displayed
In modern programming you see more and more a separation between the date (= model) and the way that the data is displayed (= view).
Separation makes it better to reuse the code, for instance: if you want to use your model in a console program, or in a WPF program, or even a different Form, you can reuse the model classes.
Separation hides how and where you fetch your data: is it a database? is it a CSV file, or XML? are you using Entity Framework
This hiding allows future changing without having to change all your Forms
This hiding also makes your Forms smaller and easier to understand
While developing the form, you can mock the actual data: just create a dummy class that provides you with sample data, without having to bother about the database
You can unit test the model, without needing a form
It is hardly any extra work.
So you'll have Model classes: your data, and how it is saved, fetched again; and View classes: your Forms. You'll need an adapter class to adapt the model to the view: the ViewModel. Together these three abbreviate to MVVM. Consider to do some background reading about MVVM.
Implementing the three advices
We create a class that makes it possible to save Bills (and other items: Customers? Orders? Products? etc) and later you can retrieve them again, even after you restarted the program. Something like a warehouse, a repository, where you store items and fetch them again.
interface IOrderRepository
{
int AddBill(Bill bill); // return Id of the Bill
Bill FindBill(int Id); // null if not found
// your GetData:
IEnumerable<Bill> FetchBillsWithNameLike(string name);
... // other methods, about Customers, Orders, etc
}
Implementation:
class OrderRepository : IOrderRepository
{
private string ConnectionString {get;} = #"Data Source=(LocalDB)";
private IDbConnection CreateConnection()
{
return new SqlConnection(this.ConnectionString);
}
The implementation of FetchBillsWithNameLike:
public IEnumerable<Bill> FetchBillsWithNameLike(string name)
{
using (IDbConnection dbConnection = this.CreateConnection())
{
const string sqlText = "Select Id, BillName, CustomerId, ..."
+ " from Bills where (billname) like %#Name%";
using (IDbCommand = dbConnection.CreateCommand())
{
// fill the command and the parameter:
dbCommand.CommandText = sqlText;
dbCommand.AddParameterWithValue("#Name", name);
// execute the command and enumerate the result
dbConnection.Open();
using (IDatareader dbReader = dbCommand.ExecuteReader())
{
while (dbReader.Read())
{
// There is a Bill to read
Bill bill = new Bill
{
Id = dbReader.ReadInt32(0),
Name = dbReader.ReadString(1),
CustomerId = dbReader.ReadInt32(2),
...
};
yield return bill;
}
}
}
}
}
// implement rest of interface
}
Several improvements:
Connection string is a property. If you decide to use a different connection string for all your 100 methods: only one place to change.
You hide where you get the connection string: here it is a constant, but if you decide in future versions to read it from the config file: no one has to know, except this method
You hide that you are using a SqlConnection, you return the interface. If in future versions you decide to create a different form of IDbConnection, for instance for a different kind of database, like SQLite, no one has to know that you create a SqlLiteConnection object instead of a SqlConnection.
Similarly: hide SqlCommand, use the interface IDbCommand.
The database connection is not opened before it is needed. This makes it possible that others can use the database as long as you will not use it.
using statements all over the place: if any exception happens, all objects are properly closed and disposed.
I don't create the DbCommand myself, I ask the DbConnection to create it for me, so I don't have to bother which type of commands the actual DbConnection uses: Is it SqlCommand? SQLiteCommand?
I specify which columns from the table if want. If in future some columns are added, and I don't need them, I won't fetch more data than I want. Similarly: if columns are reordered, it will still work.
The most important change: Use SQL parameter to prevent malicious SQL Injection.
Parameters in SQL text are often recognized by prefix #
Parameters are added with the extension method AddParameterWithValue`. Some databases have this as a method in DbCommand (for example: SQLite)
When reading the fetched data, I won't read more Bills than my caller wants. So if he calls me using the following code: not all Bills will be read:
IOrderRepository repository = ...
string name = this.ReadName();
bool billsWithNameAvailable = repository.FetchBillsWithName(name).Any();
Here, my caller only wants to know if there are any Bills with the Name at all. The reader won't create any Bills at all.
Because the SQL text is Select Id, ... and I read dbReader.GetInt32[0] etc, my code will still work, even after inserting or reordering the columns of the table.
The nice thing is, that you will be able to unit test method FetchBillsWithName without having to use a Form: you can test what happens if there is no database at all, or if there is no Bills table, or an empty table, or the table doesn't contain a column BillName. Or what happens if the input text is empty. You can unit test all kinds of errors without need of a Form.
The Form
class Form1 : ...
{
private IOrderRepository Repository {get;} = new OrderRepository();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
GetData();
}
private void GetData()
{
string name = this.txtSearch.Txt;
foreach(Bill fetchedBill in this.Repository.FetchBillsWithNameLike(name))
{
this.ProcessBill(fetchedBill);
}
}
private void ProcessBill(Bill fetchedBill)
{
// do your stuff with the label;
}
}
Because I separated the model from the view, the view is much simpler: much easier to see what really happens: you focus on the form, not on how and where you get the data.
During development, while you don't have a database yet, you can create a dummy repository and test your form:
class DummyRepository : IOrderRepository
{
private Dictionary<int, Bill> Bills {get;} = ... // fill with some sample Bills
// TODO: implement IOrderRepository, using this.Bills
}
If later you decide that you won't get your data from a database, but for instance from the internet, your form will hardly have to change. It can still use IOrderRepository
Conclusion
By separating the model from the view, both model and view are much easier to red and understand. Much easier to reuse, change, maintain and unit test. Both can be developed independantly
Procedure are small and have only one task: this makes that we can reuse the procedures. Changes are only in one procedure
By using interfaces, I hide how and where the data is fetched: SQL? CSV-file? Internet?
By using using statements the program is more full proof: after exceptions everything is property closed and disposed
By using SQL parameters I prevented malicious use of SQL injection.
I am learning to use interfaces and there is a problem when using the generated dataset.
I created two similar tables in the database, then created two data adapters in the dataset based on these tables. Then I created classes that will describe the adapter, datable and necessary methods.
My DataSet
class DB
{
public class Table1 {
public DataSetTableAdapters.Table1TableAdapter adapter;
public DataSet.Table1DataTable dataTable;
public void Init()
{
adapter = new DataSetTableAdapters.Table1TableAdapter();
dataTable = new DataSet.Table1DataTable();
}
}
public class Table2
{
public DataSetTableAdapters.Table2TableAdapter adapter;
public DataSet.Table2DataTable dataTable;
public void Init()
{
adapter = new DataSetTableAdapters.Table2TableAdapter();
dataTable = new DataSet.Table2DataTable();
}
}
}
I tried to implement, for example, like this
interface ISecondaryTable
{
DataTable dataTable { get; set; }
IDataAdapter adapter { get; set; }
}
And I tried many other options. But without results.
Does anyone know their common class?
If you open the Object Browser in visual studio (Ctrl+Alt+J in 2017, used to be Ctrl-W,J as a chord) you can see more info about the tableadapters in your project:
All TableAdapters inherit from Component. They "HAVE-A" DataAdapter, they are not "IS-A" DataAdapter. For example, they look like this:
public class XTableAdapter: Component{
private DataAdapter _da;
}
They do not look like this:
public class XTableAdapter: DataAdapter
All this said, I'm not sure why you want to treat them this way or encapsualte them along with the data table. Data is stored in the datatable, tableadapters push it between db and datatable. I don't think i've ever seen someone do, for example, a class that wraps a StreamWriter (thing that writes a file) and a String (the content of the file):
class CombinedFileContentAndWriter{
StreamWriter sw = newStreamWriter(#"C:\temp\x.txt");
string content = "Hello World";
void DoIt(){
sw.Write(content);
}
}
It's not to say you can't, it's just weird. TableAdapters are supposed to be short-to-medium life things that are called upon to move data; they don't need pairing up inseparably from that data. One tableadapter can readwrite hundreds of different instances of a datatable. TableAdapters can be created and thrown away on demand and they don't need to remain paired with the data they downloaded in order to function. You can:
var dt = new XTableAdapter().GetDataByName();
//manipulate dt in a 30 minute operation
new XTableAdapter().Update(dt); //a different tableadapter sends the data back to the DB
There's not much point trying to find a generic way to refer to tableadapters, becawuse they are all customized exactly to a specific datatable, and have names of methods that are variable, and hence not overloadable:
SchoolDataset ds = new SchoolDataSet();
new StudentTableAdapter.FillByStudentId(ds, 123);
new StaffTableAdapter.FillByStaffLastName(ds, "Smith");
new ClassroomTableAdapter.FillByYearDesignation(ds, "First grade");
This is about as deep as you need to go with tableadapters and typed datatables/sets.
The question Karen linked to is a smart resource, for sure, but it's worth noting that the lead answer chose to create a generic way to address tableadapters so they could easily enroll each adapter in a transaction, whereas Microsoft intended that to enroll tableadapter operations in a transaction they should be executed inside a TransactionScope
I basically have created a class which when a user logs into a website it then queries the database and stores some settings in a List (So I have key/pair values).
The reason for this is because I want to always be able to access these settings without going to the database again.
I put these in a class and loop through the fields via a SQL query and add them to the list.
How can I then access these variables from another part of the application? or is there a better way to do this? I'm talking server side and not really client side.
Here is an example of what I had at the moment:
public static void createSystemMetaData()
{
string constring = ConfigurationManager.ConnectionStrings["Test"].ConnectionString;
SqlConnection sql = new SqlConnection(constring);
sql.Open();
SqlCommand systemMetaData = new SqlCommand("SELECT * FROM SD_TABLES", sql);
//Set Modules
using (SqlDataReader systemMetaDataReader = systemMetaData.ExecuteReader())
{
while (systemMetaDataReader.Read())
{
var name = systemMetaDataReader.GetOrdinal("Sequence").ToString();
var value = systemMetaDataReader.GetOrdinal("Property").ToString();
var Modules = new List<KeyValuePair<string, string>>();
Modules.Add(new KeyValuePair<string, string>(name, value));
}
}
}
Thanks
Any static properties of a class will be preserved for the lifetime of the application pool, assuming you're using ASP.NET under IIS.
So a very simple class might look like:
public static class MyConfigClass
{
public static Lazy<Something> MyConfig = new Lazy<Something>(() => GetSomethings());
public static Something GetSomethings()
{
// this will only be called once in your web application
}
}
You can then consume this by simply calling
MyConfigClass.MyConfig.Value
For less users you can go with the SessionState as Bob suggested,however with more users you might need to move to a state server or load it from Data Base each time.
As others have pointed out, the risk of holding these values in global memory is that the values might change. Also, global variables are a bad design decision as you can end up with various parts of your application reading and writing to these values, which makes debugging problems harder than it need be.
A commonly adopted solution is to wrap your database access inside a facade class. This class can then cache the values if you wish to avoid hitting the database for each request. In addition, as changes are routed through the facade too, it knows when the data has changed and can empty its cache (forcing a database re-read) when this occurs. As an added bonus, it becomes possible to mock the facade in order to test code without touching the database (database access is notoriously difficult to unit test).
From the looks of things you are using universal values irrespective of users so an SqlCacheDependency would be useful here:
Make sure you setup a database dependency in web.config for the name Test
public static class CacheData {
public static List<KeyValuePair<string,string>> GetData() {
var cache = System.Web.HttpContext.Current.Cache;
SqlCacheDependency SqlDep = null;
var modules = Cache["Modules"] as List<KeyValuePair<string,string>>;
if (modules == null) {
// Because of possible exceptions thrown when this
// code runs, use Try...Catch...Finally syntax.
try {
// Instantiate SqlDep using the SqlCacheDependency constructor.
SqlDep = new SqlCacheDependency("Test", "SD_TABLES");
}
// Handle the DatabaseNotEnabledForNotificationException with
// a call to the SqlCacheDependencyAdmin.EnableNotifications method.
catch (DatabaseNotEnabledForNotificationException exDBDis) {
SqlCacheDependencyAdmin.EnableNotifications("Test");
}
// Handle the TableNotEnabledForNotificationException with
// a call to the SqlCacheDependencyAdmin.EnableTableForNotifications method.
catch (TableNotEnabledForNotificationException exTabDis) {
SqlCacheDependencyAdmin.EnableTableForNotifications("Test", "SD_TABLES");
}
finally {
// Assign a value to modules here before calling the next line
Cache.Insert("Modules", modules, SqlDep);
}
}
return modules;
}
I've got an MVC3 project and one of the models is built as a separate class library project, for re-use in other applications.
I'm using mini-profiler and would like to find a way to profile the database connections and queries that are made from this class library and return the results to the MVC3 applciation.
Currently, in my MVC3 app, the existing models grab a connection using the following helper class:
public class SqlConnectionHelper
{
public static DbConnection GetConnection()
{
var dbconn = new SqlConnection(ConfigurationManager.ConnectionStrings["db"].ToString());
return new StackExchange.Profiling.Data.ProfiledDbConnection(dbconn, MiniProfiler.Current);
}
}
The external model can't call this function though, because it knows nothing of the MVC3 application, or of mini-profiler.
One way I thought of would be to have an IDbConnection Connection field on the external model and then pass in a ProfiledDbConnection object to this field before I call any of the model's methods. The model would then use whatever's in this field for database connections, and I should get some profiled results in the MVC3 frontend.
However, I'm not sure if this would work, or whether it's the best way of doing this. Is there a better way I'm missing?
ProfiledDbConnection isn't dapper: it is mini-profiler. We don't provide any magic that can take over all connection creation; the only thing I can suggest is to maybe expose an event in your library that can be subscribed externally - so the creation code in the library might look a bit like:
public static event SomeEventType ConnectionCreated;
static DbConnection CreateConnection() {
var conn = ExistingDbCreationCode();
var hadler = ConnectionCreated;
if(handler != null) {
var args = new SomeEventArgsType { Connection = conn };
handler(typeof(YourType), args);
conn = args.Connection;
}
return conn;
}
which could give external code the chance to do whatever they want, for example:
YourType.ConnectionCreated += (s,a) => {
a.Connection = new StackExchange.Profiling.Data.ProfiledDbConnection(
a.Connection, MiniProfiler.Current);
};
I am building an application with c# and I decided to use the Enterprise Library for the DAL (SQL Server).
I don't remember where, but I had read an article about EntLib which said that the connections are closed automatically.
Is it true?
If not, what is the best approach of managing the connections in the middle layer?
Open and close in each method?
The above is a sample method of how I am using the EntLib
public DataSet ReturnSomething
{
var sqlStr = "select something";
DbCommand cmd = db.GetSqlStringCommand(sqlStr);
db.AddInParameter(cmd, "#param1", SqlDbType.BigInt, hotelID);
db.AddInParameter(cmd, "#param2", SqlDbType.NVarChar, date);
return db.ExecuteDataSet(cmd);
}
Thanks in advance.
the ExecuteDataSet method returns a DataSet object that contains all the data. This gives you your own local copy. The call to ExecuteDataSet opens a connection, populates a DataSet, and closes the connection before returning the result
for more info:
http://msdn.microsoft.com/en-us/library/ff648933.aspx
I think you should have something like a static class used as a Façade which would provide the correct connection for your library subsystems.
public static class SystemFacade {
// Used as a subsystem to which the connections are provided.
private static readonly SystemFactory _systemFactory = new SystemFactory();
public static IList<Customer> GetCustomers() {
using (var connection = OpenConnection(nameOfEntLibNamedConnection))
return _systemFactory.GetCustomers(connection);
}
public static DbConnection OpenConnection(string connectionName) {
var connection =
// Read EntLib config and create a new connection here, and assure
// it is opened before you return it.
if (connection.State == ConnectionState.Closed)
connection.Open();
return connection;
}
}
internal class SystemFactory {
internal IList<Customer> GetCustomers(DbConnection connection) {
// Place code to get customers here.
}
}
And using this code:
public class MyPageClass {
private void DisplayCustomers() {
GridView.DataSource = SystemFacade.GetCustomers();
}
}
In this code sample, you have a static class that provides the functionalities and features of a class library. The Façade class is used to provide the user with all possible action, but you don't want to get a headache with what connection to use, etc. All you want is the list of customers out of the underlying datastore. Then, a call to GetCustomers will do it.
The Façade is an "intelligent" class that knows where to get the information from, so creates the connection accordingly and order the customers from the subsystem factory. The factory does what it is asked for, take the available connection and retrieve the customers without asking any further questions.
Does this help?
Yes, EntLib closes connections for you (actually it releases them back into the connection pool). That is the main reason why we originally started to use EntLib.
However, for all new development we have now gone on to use Entity Framework, we find that much more productive.