简体   繁体   中英

Calling class to do database connection

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

  1. Getting rid of the inheritance
  2. Make the database class a static class (no reason to instantiate a database instance here)
  3. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM