2014-09-04 6 views
1

내 프로그램 전체에서 SELECT 명령 (MySQL)을 반복적으로 사용하려고합니다. 매번 연결과 물건을 만들어야합니다. SELECT 명령 문자열을 받고 인수의 동등한 DataReader를 반환하는 메서드를 만들려고합니다. 나는 이것이 내가 매번 생성해야하는 코드의 큰 덩어리를 줄이는 데 도움이 될 것이라고 생각한다.C# 및 MySQL - 메서드 DataReader (또는 그 내용) 반환

는 그와 같은 방법으로 그것을 사용하려면 :

MySqlDataReader myReader = myObj.loadDataToReader("SELECT * FROM tblSample"); 

을 그리고, 나는 정기적 MySqlDataReader 같은 myReader을 조작 할 수 있습니다. 그러나 데이터 웨어레이터를 사용할 때 연결이 열려 있어야한다는 사실에 대해 우려하고 있습니다. 물론 그것에 대한 문제 (판독기와 연결)가 닫혀 있어야하고 모든 것이 안전해야한다고 생각합니다.). 나는 인터넷에서 사물을보고 있었고, 나는 이것을하는 방법에 대한 힌트를 찾을 수없는 것 같습니다.

나는 시도하고 난 다음 코드 줄이 있습니다

public MySqlDataReader loadDataToReader(string selectCommand) 
{ 
    MySqlDataReader myReader = null; 
    string myConnectionString = "Data Source = " + server + "; User = " + user + "; Port = 3306; Password = " + password + ";"; 
    string useDataBaseCommand = "USE " + dbName + ";"; 
    using (MySqlConnection myConnection = new MySqlConnection(myConnectionString)) 
    { 
     using (MySqlCommand myCommand = new MySqlCommand(useDataBaseCommand + selectCommand, myConnection)) 
     { 
      try 
      { 
       myConnection.Open(); 
       myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection); 
      } 
      catch (Exception ex) 
      { 
       myConnection.Close(); 
       MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
      return myReader; 
     } 
    } 
} 

그리고 다른 클래스의 방법

, 나는 그것을하는 방식으로, 위에서 정의 된 방법을 사용할 수 있도록 객체를 생성을

string selectTableCommand = "SELECT * FROM tblusers WHERE Username = \'" + txtID.Text + "\' AND Password = \'" + txtPassword.Text + "\';"; 
MySQLOperations objSQLOperations = new MySQLOperations("localhost", "root", "mypass", "mydatabase"); 
MySqlDataReader myDataReader = objSQLOperations.loadDataToReader(selectTableCommand); 
if (myDataReader.Read() && txtPassword.Text.Equals(myDataReader["Password"].ToString())) 
    { /* do something */ } 
else 
    { /* do something */ } 

그러나 "리더가 닫혔을 때 잘못된 시도가 있습니다!"라는 메시지가 나타납니다. 어떻게 해결하고 작동하게 할 수 있습니까? 아니면이 일을하는 훨씬 더 적절한 방법이 있습니까? 그리고 연결/판독기가 사용 된 후에 어떻게 닫히게할까요?

당신은 당신의 방법은 일반적인하고 독자에서 작동하는 기능을 삽입 할 수
+0

대신 DataTable을 사용하십시오.판독기를 데이터 테이블에로드하십시오. 즉,'var dt = new DataTable(); dt.Load (myReader);'그런 다음 DataTable을 호출자에게 반환하여 호출자에게 처리합니다. – adaam

+0

DataSet 또는 DataTable은 종종 DataReader보다 더 나은 선택입니다. 또한 SQL 문을 연결하지 않고 SQL 문을 매개 변수화해야합니다. http://en.wikipedia.org/wiki/SQL_injection –

+0

아이디어를 제공해 주셔서 감사합니다. 대신 DataTable을 사용할 것입니다. – Jill

답변

3

후 오히려 독자보다 함수의 출력을 반환 :

  • :

    public T LoadDataToReader<T>(string selectCommand, Func<IDataReader,T> ProcessResults) 
    { 
        string myConnectionString = "Data Source = " + server + "; User = " + user + "; Port = 3306; Password = " + password + ";"; 
        string useDataBaseCommand = "USE " + dbName + ";"; 
        using (var myConnection = new MySqlConnection(myConnectionString)) 
        { 
         myConnection.Open(); 
    
         using (var myCommand = myConnection.CreateCommand()) 
         { 
          myCommand.CommandText = useDataBaseCommand + selectCommand; 
    
          using(var myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection)) 
          { 
           return ProcessResults(myReader); 
          } 
         } 
        } 
    } 
    

    가 나는 또한 다른 변경을 IDataReaderIDisposable을 구현하므로 독자에게 using 문을 추가했습니다.

  • 생성자가 아닌 명령을 만드는 데 ADO.NET 인터페이스 메서드를 사용했습니다.
  • 사용 블록을 나가면 연결 닫기가 자동으로 수행되고 UI 코드 (예 : MessageBox)가 DAL 코드에 속하지 않으므로 catch 블록을 제거했습니다. 이것은 대신이 메소드를 호출 할 때 try/catch로 수행되어야합니다. 당신은 아마 연결을 통과해야,

    public static string GetStringData(IDataReader reader) 
    { 
        var ord_name = reader.GetOrdinal("Name"); 
    
        if(reader.Read()) 
        return reader.GetString(ord_name); 
    
        return null; 
    } 
    
    public static IEnumerable<Foo> GetFoos(IDataReader reader) 
    { 
        var ord_name = reader.GetOrdinal("Name"); 
        var foos = new List<Foo>(); 
    
        while(reader.Read()) 
        foos.Add(new Foo {Name = reader.GetString(ord_name)}); 
    
        return foos; 
    } 
    
    static void Main(string[] args) 
    { 
        var program = new Program(); 
        try 
        { 
         var name = program.LoadDataToReader("SELECT name FROM thename", GetStringData); 
        } 
        catch(Exception ex) 
        { 
         MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); 
        } 
        try 
        { 
         var foos = program.LoadDataToReader("SELECT foos FROM footable", GetFoos); 
        } 
        catch(Exception ex) 
        { 
         MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); 
        } 
    } 
    

    을 추가 :

  • 나는 다음과 같이 간단하게 사용

그리고 .NET 코딩 표준이 일치하도록 함수의 첫 글자를 대문자로 필드에서 필드를 작성하는 대신 문자열을 입력하십시오. 또는 전체 연결 문자열 (모든 실행이 아니라 한 번만 빌드 됨)에 대한 필드를 설정하고이를 사용할 수 있습니다.

또한 Initial Catalog 또는 Database으로 데이터베이스를 연결 문자열로 설정할 수 있습니다.이 경우 select 문 앞에 USE database 절을 붙이는 것이 좋습니다.

+0

필자는 위의 작업을 수행하여 DataTable로 변경하려고 결정했습니다. 고마워요, 선생님. 언젠가는이 방법을 사용할 수있을 것입니다. – Jill

+0

@Jill DataSet과 DataTable은 모두 IDisposable입니다. 데이터 어댑터는 결과 집합 스키마를 결정하기 위해 추가 단계를 수행해야하기 때문에 메모리와 쿼리 측면에서 꽤 무거운 객체입니다. Entity Framework 나 nHibernate와 같은 ORM을 사용하는 것이 제안 된 옵션 중 어느 것보다 좋을지라도, 데이터 판독기를 사용하는 것이 좋습니다. –