简体   繁体   English

调用类进行数据库连接

[英]Calling class to do database connection

I'm programming in C#. 我在用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(); 我以为放在class Program : db会在程序打开时调用db构造函数,但是当代码到达该行时dataReader = query.ExecuteReader(); , it comes up with the error "ExecuteReader: Connection property has not been initialized.". ,出现错误“ ExecuteReader:连接属性尚未初始化”。

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 . 不,什么都没有创建Program实例,什么也没有创建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 不要对此类事情使用继承-您的Program类型在逻辑上不是从db派生的
  • Follow .NET naming conventions for methods, classes and properties. 对于方法,类和属性,请遵循.NET命名约定。 Making your code "feel" like idiomatic C# will go a long way to making it more readable for other people. 使您的代码像惯用的C#一样“感觉”将大大提高其可读性。

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(); 然后,您的程序可以使用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. 您应该隐藏OleDbCommand和OleDbDatareader对象的详细信息,尽管并不需要在其他地方对其进行管理。 Your getHousesFromDB should be called like: 您的getHousesFromDB应该这样称呼:

MyDBClass.GetHousesFromDB()

Where MyDBClass is a static class that manages your database read / writes. 其中MyDBClass是管理数据库读/写的静态类。 The signature of GetHousesFromDB should return something to the effect of IList<House> GetHousesFromDB() GetHousesFromDB的签名应该返回一些东西,以达到IList<House> GetHousesFromDB()的效果。

Though Jon Skeet & JonH make valid points, I'll answer why you're getting the exception. 尽管乔恩·斯凯特(Jon Skeet)和乔恩(JonH)提出了正确的观点,但我会回答您为什么会得到例外的原因。 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. 出现异常的原因是它是在db的构造函数中初始化的,并且永远不会被调用。

If you add this line to Main , your program should work. 如果将此行添加到Main ,则程序应该可以运行。

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. 在许多情况下,这些玩具项目迅速发展为功能完善的企业应用程序,一旦您到达那里,一开始的错误就永远存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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