2012-01-15 90 views
2

在我目前编写的应用程序中,我处理了很多MySql数据库。我知道我这样做的方式是错误的,所以你不需要告诉我,但我该如何正确地做到这一点?如同从.NET应用程序处理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(); 
     } 
    } 
} 

我实例化这个类,然后使用选择的方法来选择,像这样的数据:

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';"); 

在你开始之前,是的,我为自己的sl sl sl code的代码感到非常羞愧,但如果你能帮助我提高,我会非常感激!

谢谢

+3

你应该包装在using语句您的MySqlConnection类,以确保即使出现错误,连接也会关闭。 – Hans 2012-01-15 17:47:19

+0

这似乎是可行的,那么我的代码中的原始SQL呢?我的理解是,这只是一个庞大的nono,对连接参数进行硬编码。 – JMK 2012-01-15 17:49:56

+3

您还应该使用类型安全的MySqlParameter来防止SQL注入代码。对于SQL注入,请参阅以下链接http://msdn.microsoft.com/en-us/library/ff648339.aspx。 – Hans 2012-01-15 18:21:21

回答

6

首先,我会创建一个接口,将您的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); 
     } 
    } 
} 

显然有一堆的错误处理,依赖注入的设置和其他的东西去在那里,但希望ully这应该给你一个结构从:)

+0

这很棒,我知道必须有更好的方式来做到这一点!谢谢! – JMK 2012-01-16 07:56:54

+0

不客气,祝你好运:) – 2012-01-16 09:37:53

3

这里没有具体的MySQL。如果你正在处理多个DBMS,那么一种方法是使用.net db接口IDbCommand,IDbConnection等。

将连接字符串放在app.config或其他类中。

原始SQL在你的代码中,不好?你可以看看实体框架,LinQToSQL,一个基于存储过程的设计,但这是一个好去处,学习和看看有什么适合。很多原始SQL的真正问题是,您的代码与您的后端密切相关。管理这个技巧的诀窍是“把它放在一个地方”。一个'model'.dll,每个类中的一个接口。一次类来处理每个表等。不要乱丢你的代码库。通过遍历整个代码库,因为您重命名了订单表,这是不行的。

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

正如@Hans所说的那样使用,你会在整个地方发现潜在的资源泄漏。

+0

谢谢,我更新了从MySql到DBMS的标签,并且对于回复,它帮助了很多! – JMK 2012-01-16 07:54:57

0

开始扩大TrueWill的评论:

照顾会话类型,锁定交易等,这取决于你的需求进行并发

Here is a tutorial

相关问题