【问题标题】:Creating a class to interact with a SQL database创建一个与 SQL 数据库交互的类
【发布时间】:2012-11-04 19:14:39
【问题描述】:

我熟悉编程中的主要面向对象概念,目前我正在自学如何设计类。

我有一个非常简单的类,叫做 Company。这是我到目前为止的代码

using System;

namespace Addressbook
{
    public class Company
    {
        private string _companyId;
        private string _companyName;
        private string _companyType;
        private string[] _companyDetails;

        public Company()
        {

        }


        public string CompanyId
        {
            set
            {
                this._companyId = value;
            }
        }

        public string CompanyName
        {
            set
            {
                this._companyName = value;
            }
        }

        public string CompanyType
        {
            set
            {
                this._companyType = value;
            }
        }


        public string[] GetCompanyDetails()
        {

            return null;
        }

    }
}

我现在要做的是实现一些方法,这就是我迷失的地方。

我想到的第一种方法称为GetCompanyDetails(),它会从 SQL 数据库中收集数据,然后将其显示出来。可能在 DataGridView 或其他东西中。

我的问题是我不知道应该如何编写这个方法。我是否将所有 SQL 查询和连接放入其中?还是我只是将它们的实例作为参数传递?我应该从方法返回什么类型?

有人可以给我一些指导吗?

此外,如果您有任何关于此主题的优秀教程/指南的链接,请也发布它们。

谢谢。

【问题讨论】:

  • 我不是专业人士,但我接受过培训,可以声明一个新类,该类包含所有返回 string 的查询。

标签: c# oop class methods


【解决方案1】:

我的自制 ADO 对象映射器: 构建一个简单的类,

public class Company
{       
    public string CompanyId { get; set; }
    public string CompanyName{ get; set; }
    public string CompanyType{ get; set; }       
}

使用此方法进行对象映射:

public List<T> GetData<T>(string SQL, CommandType commandType, string ConnectionString) 
{
    var objProps = Activator.CreateInstance<T>().GetType().GetProperties();
    var returnList = new List<T>();
    using (SqlConnection con = new SqlConnection(ConnectionString)) {
        using (SqlCommand cmd = new SqlCommand(SQL, con)) {
            cmd.CommandType = commandType;
            cmd.CommandTimeout = 30000;
            try
            {                  
                con.Open();
                SqlDataReader reader = cmd.ExecuteReader();
                var columns = reader.GetSchemaTable().Rows.Cast<DataRow>().Select(row => row["ColumnName"].ToString().ToLower()).ToList();
                while (reader.Read())
                {
                    var thisRow = Activator.CreateInstance<T>();
                    foreach (var prop in objProps)
                    {                         
                        if (columns.Contains(prop.Name.ToLower()))
                        {
                            prop.SetValue(thisRow, reader[prop.Name]);
                        }
                    }
                    returnList.Add(thisRow);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally {
                if (con.State != ConnectionState.Closed)
                {
                    con.Close();
                }
            }
        }
    }
    return returnList;
}

这样调用方法:

var companyInfo = GetData<Company>("ProcName", CommandType.StoredProcedure, "con-str");

【讨论】:

    【解决方案2】:

    在下面使用我们正在使用的类文件:

    /// <summary>
    /// Open the Connection when creating the Object
    /// </summary>
    class DataAccess
    {
        public SqlConnection sqlConn ;
        public int gConnTimeOut = 0 ;
    
        public DataAccess()
        {
            string strConn = "";            
    
            Classes.GlobVaribles objConStr = Classes.GlobVaribles.GetInstance();
            strConn = objConStr.gConString;
            gConnTimeOut = objConStr.gQueryTimeOut;
    
            if (strConn == "")
            {
                XmlAccess XmlFile = new XmlAccess();
                strConn = XmlFile.Xml_Read("gConStr");
                gConnTimeOut = int.Parse(XmlFile.Xml_Read("gQueryTimeOut"));
    
                objConStr.gConString = strConn;
                objConStr.gQueryTimeOut = gConnTimeOut;
            }
    
            sqlConn =  new SqlConnection(strConn);            
            sqlConn.Open();
        }
    
        /// </summary>
        /// Can use to select one value from SELECT statment
        /// </summary>
        public string SQLER(string strSQL)
        {
            if (sqlConn.State.ToString() == "Closed") { sqlConn.Open(); }
    
            strSQL = SQLFormat(strSQL);
            SqlCommand sqlCmd = new SqlCommand(strSQL, sqlConn);
    
            string strResult = sqlCmd.ExecuteScalar().ToString();
            sqlCmd.Dispose();
    
            return strResult;
    
        }
    
        /// </summary>
        /// Return Data Set        
        /// </summary>
        public DataSet SQLDT(string strSQL)
        {
            //conn.Close();
    
            //if (conn.State.ToString() == "Closed") { conn.Open(); }
            if (sqlConn.State.ToString() == "Closed") { sqlConn.Open(); }
            SqlCommand comm = new SqlCommand();
            comm.CommandTimeout = gConnTimeOut;
            SqlDataAdapter adapt = new SqlDataAdapter();
            comm.CommandText = strSQL;
            comm.Connection = sqlConn;
            adapt.SelectCommand = comm;
    
            DataSet dtset = new DataSet();
            adapt.Fill(dtset);
            return dtset;
    
        }
    
       /// <summary>
        /// Can use for Execute SQL commands (Insert/Delete/Update)
        /// </summary>
        public int SQLCX(string strSQL)
        {
            try
            {
                if (sqlConn.State.ToString() == "Closed") { sqlConn.Open(); }
    
                strSQL = SQLFormat(strSQL);
                SqlCommand sqlCmd = new SqlCommand(strSQL, sqlConn);
                sqlCmd.CommandTimeout = gConnTimeOut;
                int intResult = sqlCmd.ExecuteNonQuery();
                sqlCmd.Dispose();
    
                return intResult;
            }
            catch (Exception objError)
            {
                MessageBox.Show("System Error - " + objError.Message.ToString(),"Application Error",MessageBoxButtons.OK,MessageBoxIcon.Error );
                return -1;
            }
    
        }
    
        /// <summary>
        /// Returns a SQL DataReader
        /// </summary>       
        public SqlDataReader DataReader(string strSQL)
        {
            if (sqlConn.State.ToString() == "Closed") { sqlConn.Open(); }
            strSQL = SQLFormat(strSQL);
            SqlCommand sqlCmd = new SqlCommand(strSQL, sqlConn);
            SqlDataReader dataRed = null;
    
            dataRed = sqlCmd.ExecuteReader(CommandBehavior.CloseConnection);
            sqlCmd.Dispose();
            return dataRed;
        }
    
        /// <summary>
        /// Retrun the No of Records
        /// </summary>
        public int GetNumOfRec(string strSQL)
        {
            /// Use for get No of Records in SELECT command
            try
            {
                int intResult = -1;
                if (sqlConn.State.ToString() == "Closed") { sqlConn.Open(); }
    
                strSQL = SQLFormat(strSQL);
                SqlCommand sqlCmd = new SqlCommand(strSQL, sqlConn);
                intResult = (int)sqlCmd.ExecuteScalar();
                sqlCmd.Dispose();
    
                return intResult;
            }
            catch (Exception objError)
            {
                MessageBox.Show("System Error - " + objError.Message.ToString(), "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return -1;
            }
        }
    
        /// </summary>
        /// Fill Listview 
        /// </summary>
        public void ListViewFill(string strSQL, System.Windows.Forms.ListView lstView)
        {
            if (sqlConn.State.ToString() != "Open") { sqlConn.Open(); }
            SqlDataAdapter adapter = new SqlDataAdapter(strSQL, sqlConn);            
            DataSet ds = new DataSet("glorders");
            adapter.SelectCommand.CommandTimeout = gConnTimeOut;
            adapter.Fill(ds, "glorders");
    
            DataTable dt = ds.Tables[0];
            int colCount = dt.Columns.Count;
    
           lstView.Items.Clear();
           Color shaded = Color.FromArgb(240, 240, 240);
           int j = 0;
    
            foreach (DataRow row in dt.Rows)
            {
                string[] subitems = new string[colCount];
    
                object[] o = row.ItemArray;
    
    
                for (int i = 0; i < colCount; i++)
                {
                    subitems[i] = o[i].ToString();                      
                }
    
                ListViewItem item = new ListViewItem(subitems);
                lstView.Items.Add(item);
    
                if (j++ % 2 == 1)
                {
                    item.BackColor = shaded;
                    item.UseItemStyleForSubItems = true;
                }
            }
    
            dt.Dispose();
            ds.Dispose();
            adapter.Dispose();
        }
    
        /// </summary>
        /// Fill ComboBox
        /// </summary>
        public void ComboFill(string strSQL, System.Windows.Forms.ComboBox dbCombo)
        {
            SqlDataReader dbReader = null;
            dbReader = DataReader(strSQL);
            dbCombo.Items.Clear();
            while (dbReader.Read()) { dbCombo.Items.Add(dbReader[0].ToString().Trim()); }
            dbReader.Dispose();
        }
    
        private string SQLFormat(string strSQL)
        {
            strSQL = strSQL.Replace("\r", " ");
            strSQL = strSQL.Replace("\n", " ");
            strSQL = strSQL.Replace("\t", " ");
            strSQL = strSQL.Replace("  ", " ");
            return strSQL;
        }
    }
    

    【讨论】:

      【解决方案3】:
      String conString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
      OracleConnection con = new OracleConnection(conString);
      string cmdStr = @" SELECT * FROM TABLE WHERE ROW = :param";
      OracleCommand cmd = new OracleCommand(cmdStr, con);
      OracleDataAdapter da = new OracleDataAdapter(cmd);
      da.SelectCommand = cmd;
      cmd.Parameters.Add("param", "yourValueHere");
      
      DataSet ds = new DataSet("dataSet");
      da.Fill(ds, "dataAdapter");
      return ds;
      

      是实现数据库类的好方法。还记得用

      标记你的方法
      [DataObjectMethod(DataObjectMethodType.Select, true)]
      

      如果您希望它可以在您的 WPF 中实现。

      【讨论】:

        【解决方案4】:

        首先,您的代码太长太旧了。你的代码应该是这样的

        public class Company
        {       
                public string CompanyId { get; set; }
                public string CompanyName{ get; set; }
                public string CompanyType{ get; set; }       
        }
        

        当你创建这个类时,这意味着你创建了一个对象Company,它有3个字段;

        Company.CompanyIdCompany.CompanyNameCompany.CompanyType

        所以你现在要做的就是连接到 SQL 服务器,执行查询以从数据库中获取数据并填写一个对象公司。

        例子:

        class myConnection
            {
                public static SqlConnection GetConnection()
                {
                    var company = new Company();
                    string str = "Data Source=localhost/serer Ip;Initial Catalog = YourDatabaseName;uid =sa;pwd = YourPassword";
        
                    SqlConnection con = new SqlConnection(str);          
                    SqlCommand cmd = new SqlCommand("SELECT * FROM Company WHERE CompanyID = 1", conn);
                    SqlDataReader reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        Company.CompanyId = reader["CompanyID"];
                        Company.CompanyName = reader["Name"];
                        Company.CompanyType = reader["Type"];
                    }
                }
            } 
        

        【讨论】:

          【解决方案5】:

          创建代表表中记录的类

          public class Company
          {       
              public string CompanyId { get; set; }
              public string CompanyName{ get; set; }
              public string CompanyType{ get; set; }       
          }
          

          使用Dapper获取并映射它:

          public IEnumerable<Company> GetCompanies()
          {
             using (var connection = new SqlConnection(connectionString))
             {
                 connection.Open();
                 return connection.Query<Company>("SELECT * FROM Companies");
             }
          }
          

          如果您不想处理 ADO.NET,请查看重量级的 ORM,例如 Linq 2 Sql、Entity Framework、NHibernate。

          【讨论】:

          • 感谢 Dapper 提示。不知道。
          【解决方案6】:

          查看“数据源架构模式”部分中的模式:http://martinfowler.com/eaaCatalog/index.html。 ActiveRecord 模式可能是您需要的,尽管您最终可能会选择 DataMapper/ORM 路线。

          本着敏捷精神,我最初会保持连接和事务管理非常简单。也许只是这个类中的一个私有函数。然后我会让每个方法在 SQL 或 SP 中定义它的查询并执行它并对结果做一些事情。这将数据访问逻辑保持在适当的位置。

          您可能希望将“getter”函数设为共享/静态,这样就不需要实例即可开始运行。然后你可以这样写:

          var companies = Company.GetCompanyDetails();
          

          虽然非常简单,但这种方法可以让您继续前进,同时仍然允许您扩展范围。一旦事情开始变得更加复杂,这种方法将被证明过于简单。此时,您需要扩展和重构,考虑更强大的连接/事务管理、对象创建和查询。

          【讨论】:

            【解决方案7】:

            首先,我建议您检查这个问题:Using an ORM or plain SQL?。如果您不打算执行异国情调和繁重的查询,ORM 是您的首选

            我更喜欢实体框架,但您可以选择其中任何一个。

            然后,如果您想更深入,请查看存储库和工作单元模式。有一篇关于在 .net 中实现它们的好文章:Implementing the Repository and Unit of Work Patterns

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2010-09-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多