【问题标题】:What is the correct way to deal with a MySql database from a .Net application从.Net应用程序处理MySql数据库的正确方法是什么
【发布时间】:2012-01-15 17:31:16
【问题描述】:

在我目前编写的应用程序中,我经常处理几个 MySql 数据库。我知道我这样做是错误的,所以你不需要告诉我,但是我该如何以正确的方式做到这一点?例如,从 .Net 应用程序处理 MySql 数据库的正确做法是什么。

此刻我正在使用一个类,如下所示:

using System;
using MySql.Data.MySqlClient;

namespace WhateverProjectImWorkingOn
{
    class MySql
    {
        public string myConnectionString = String.Format("SERVER={0}; DATABASE={1}; UID={2}; PASSWORD={3}", "8.8.8.8", "foobar", "foo", "barr");

        public string Select(string mySqlQuery)
        {
            MySqlConnection connection = new MySqlConnection(myConnectionString);
            MySqlCommand command = connection.CreateCommand();
            MySqlDataReader Reader;

            command.CommandText = mySqlQuery;

            connection.Open();

            Reader = command.ExecuteReader();

            string thisrow = "";

            while (Reader.Read())
            {
                for (int i = 0; i < Reader.FieldCount; i++)
                {
                    thisrow += Reader.GetValue(i).ToString();
                }
            }

            Reader.Close();
            connection.Close();
            return thisrow;
        }

        public void Update(string mySqlQuery)
        {
            MySqlConnection mangoConnection = new MySqlConnection(myConnectionString);
            MySqlCommand command = mangoConnection.CreateCommand();

            command.CommandText = mySqlQuery;

            mangoConnection.Open();
            MySqlDataReader reader = command.ExecuteReader();
            mangoConnection.Close();
        }
    }
}

我实例化这个类,然后使用 Select 方法来选择数据,如下所示:

MySql mySql = new MySql();
string whateverIWant = mySql.Select("Select `MyValue` From `FooBarr` Where `Foo` = 'Barr'");

我像这样运行更新查询:

mySql.Update("UPDATE `tblFooBarr` SET `acme`='Foo' WHERE `tnt`='barr';");

在你开始之前,是的,我为自己草率的代码感到非常羞愧,但如果你能帮助我改进,我将不胜感激!

谢谢

【问题讨论】:

  • 您应该将 MySqlConnection 类包装在 using 语句中,以确保即使出现错误也关闭连接。
  • 这似乎可行,那我代码中的原始 SQL 呢?我的理解是,这只是一个巨大的 nono,就像硬编码连接参数一样。
  • 您还应该使用类型安全的 MySqlParameter 来保护您的代码免受 SQL 注入。 SQL注入见以下链接msdn.microsoft.com/en-us/library/ff648339.aspx。
  • 你可以使用 NHibernate - 例如见How to configure fluent nHibernate with MySQL。

标签: c# .net database


【解决方案1】:

首先,我会在您的 MySql 数据库和您的代码之间创建一个接口。这将您的应用程序与 MySql 数据库类分离;像这样:

public interface IDbProvider : IDisposable
{
    void Open();
    void BeginTransaction();
    IDataReader ExecuteReader(string query);
    int ExecuteNonReader(string query);
    int GetLastInsertId();
    void Commit();
    void Rollback();
    void Close();
}

在您的 MySql 特定的 IDbProvider 实现中,您应该从 ConfigurationManager.ConnectionStrings 集合中获取连接字符串,而不是对其进行硬编码。

接下来,您可以将查询放在自定义配置部分中,该部分会从您的代码中获取硬编码、特定于 MySql 语法的查询,如下所示:

<queries>
  <SelectFoo>
    <![CDATA
    Select `MyValue` From `FooBarr` Where `Foo` = '{value}'
    ]>
  </SelectFoo>
</queries>

...然后使用自定义配置提供程序通过枚举和库类向您的应用程序公开这些查询,从而将您的应用程序与其使用 SQL 的知识分离:

public enum AvailableQuery
{
    SelectFoo
}

public class QueryLibrary
{
    private readonly AvailableQueryConfigSection _availableQueries;

    public QueryLibrary()
    {
        this._availableQueries = 
            (AvailableQueryConfigSection)
            ConfigurationManager.GetSection("queries");
    }

    public string GetQuery(AvailableQuery query)
    {
        // return query from availableQueries
    }
}

最后,您可以拥有一个repository 类,该类使用QueryLibrary 将查询发送到IDbProvider,以便它可以返回对象或执行更新,从而将您的应用程序与数据库完全分离:

public class FooRepository
{
    public Foo GetFooByValue(string value)
    {
        string query = this._queryLibrary
            .GetAvailableQuery(AvailableQuery.SelectFoo)
            .Replace("{value}", value); // <- or better still, use parameters

        using (IDataReader reader = this._dbProvider.ExecuteReader(query))
        {
            // Or get the values out of the reader here and pass them into 
            // a constructor instead of passing in the reader itself:
            return new Foo(reader);
        }
    }
}

显然有一堆错误处理、依赖注入设置和其他东西要进去,但希望这会给你一个结构来开始:)

【讨论】:

  • 这太好了,我知道一定有更好的方法来做到这一点!谢谢!
【解决方案2】:

这里没有特定于 MySQL 的内容。如果您要处理多个 DBMS,那么一种方法是使用 .net db 接口 IDbCommand、IDbConnection 等。

将连接字符串放在 app.config 之类的。

您的代码中有原始 SQL,不好吗?您可以查看实体框架、LinQToSQL,这是一种基于存储过程的设计,但您可以试一试,学习并看看什么适合。大量原始 SQL 的真正问题是您的代码与后端密不可分。管理它的诀窍是“把它放在一个地方”。一个'model'.dll,每个类一个接口。一次处理每个表等。不要乱扔代码库。因为您重命名了订单表,所以遍历整个代码库,这是不行的。

你为什么在 Update() 方法中使用阅读器??? Command 有一个方法。

正如@Hans 所说,看看使用,你到处都有潜在的资源泄漏。

【讨论】:

  • 谢谢,我把标签从MySql更新到了DBMS,也为了回复,帮了大忙!
【解决方案3】:

扩展 TrueWill 的评论:

根据您的并发需求处理会话类型、锁定、事务等

Here is a tutorial

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    • 1970-01-01
    • 2019-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多