2012-03-18 3 views
5

Sto sviluppando un'applicazione CMS in C# (4.0 Framework) che si collega al database MySQL (5.0.95) sul server remoto tramite MySQL Connector (6.5.4).C# con MySQL tramite connettore/NET

Ho problemi con l'esecuzione di query.

ad es. La mia stringa di connessione:

"Server=" + Options.DbServer + ";Database="+ Options.Database +";Uid=" + Options.DbUser + ";Pwd=" + Options.DbPassword + ";CharSet=utf8; Connect Timeout=30;"; 

devo classe statica che gestisce cose relative base di dati, e non vi ho _connection membro privato.

private static MySqlConnection _connection; 
public static MySqlConnection Connection 
{ 
    get 
    { 
     if (_connection.State != ConnectionState.Open) 
      _connection.Open(); 

     return _connection; 
    } 
    set { _connection = value; } 
} 

Questo è il metodo che inizializza collegamento:

public static bool Init(string cs) 
{ 
    _connection = new MySqlConnection(cs); 
    MySqlCommand command = new MySqlCommand("SET NAMES utf8", Connection); 
    command.ExecuteNonQuery(); 
    return true; 
} 

Questo è il metodo in cui ottengo un'eccezione:

public static bool InsertRecord(MySqlCommand command) 
{ 
    command.Connection = Connection; 
    if(command.ExecuteNonQuery() > 0) 
     return true; 

    return false; 
} 

command.ExecuteNonQuery() tiri eccezione: Errore irreversibile incontrata durante l'esecuzione del comando.

Questo è traccia dello stack ...

MySql.Data.MySqlClient.MySqlException was unhandled 
    Message=Fatal error encountered during command execution. 
    Source=MySql.Data 
    ErrorCode=-2147467259 
    Number=0 
    StackTrace: 
     at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) 
     at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery() 
     at CMS.Database.InsertRecord(MySqlCommand command) in C:\_myStuff\VS2010\CMS\CMS\Database.cs:line 95 
     at CMS.frmAddItem.btnDo_Click(Object sender, EventArgs e) in C:\_myStuff\VS2010\CMS\CMS\frmAddItem.cs:line 138 
     at System.Windows.Forms.Control.OnClick(EventArgs e) 
     at System.Windows.Forms.Button.OnClick(EventArgs e) 
     at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) 
     at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
     at System.Windows.Forms.Control.WndProc(Message& m) 
     at System.Windows.Forms.ButtonBase.WndProc(Message& m) 
     at System.Windows.Forms.Button.WndProc(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
     at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
     at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
     at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.RunDialog(Form form) 
     at System.Windows.Forms.Form.ShowDialog(IWin32Window owner) 
     at System.Windows.Forms.Form.ShowDialog() 
     at CMS.frmMain.btnNovi_Click(Object sender, EventArgs e) in C:\_myStuff\VS2010\CMS\CMS\frmMain.cs:line 381 
     at System.Windows.Forms.Control.OnClick(EventArgs e) 
     at System.Windows.Forms.Button.OnClick(EventArgs e) 
     at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) 
     at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
     at System.Windows.Forms.Control.WndProc(Message& m) 
     at System.Windows.Forms.ButtonBase.WndProc(Message& m) 
     at System.Windows.Forms.Button.WndProc(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
     at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
     at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
     at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.RunDialog(Form form) 
     at System.Windows.Forms.Form.ShowDialog(IWin32Window owner) 
     at System.Windows.Forms.Form.ShowDialog() 
     at CMS.frmLogin.DoLogin() in C:\_myStuff\VS2010\CMS\CMS\frmLogin.cs:line 55 
     at CMS.frmLogin.button2_Click(Object sender, EventArgs e) in C:\_myStuff\VS2010\CMS\CMS\frmLogin.cs:line 31 
     at System.Windows.Forms.Control.OnClick(EventArgs e) 
     at System.Windows.Forms.Button.OnClick(EventArgs e) 
     at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) 
     at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
     at System.Windows.Forms.Control.WndProc(Message& m) 
     at System.Windows.Forms.ButtonBase.WndProc(Message& m) 
     at System.Windows.Forms.Button.WndProc(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
     at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
     at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
     at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.Run(Form mainForm) 
     at CMS.Program.Main() in C:\_myStuff\VS2010\CMS\CMS\Program.cs:line 18 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: MySql.Data.MySqlClient.MySqlException 
     Message=Fatal error encountered attempting to read the resultset. 
     Source=MySql.Data 
     ErrorCode=-2147467259 
     Number=0 
     StackTrace: 
      at MySql.Data.MySqlClient.MySqlDataReader.NextResult() 
      at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) 
     InnerException: MySql.Data.MySqlClient.MySqlException 
      Message=Reading from the stream has failed. 
      Source=MySql.Data 
      ErrorCode=-2147467259 
      Number=0 
      StackTrace: 
       at MySql.Data.MySqlClient.MySqlStream.LoadPacket() 
       at MySql.Data.MySqlClient.MySqlStream.ReadPacket() 
       at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int32& insertedId) 
       at MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int32& insertedId) 
       at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force) 
       at MySql.Data.MySqlClient.MySqlDataReader.NextResult() 
      InnerException: System.IO.EndOfStreamException 
       Message=Attempted to read past the end of the stream. 
       Source=MySql.Data 
       StackTrace: 
         at MySql.Data.MySqlClient.MySqlStream.ReadFully(Stream stream, Byte[] buffer, Int32 offset, Int32 count) 
         at MySql.Data.MySqlClient.MySqlStream.LoadPacket() 
       InnerException: 

Qualche suggerimento?

+2

'Message = Tentativo di leggere oltre la fine dello stream. - Stai eseguendo un _reader_ da qualche parte. – Oded

+1

Lo stacktrace indica che ExecuteNonQuery chiama ExecuteReader. Direi che non ti stai ancora connettendo correttamente al database. Hai mai avuto modo di chiamare 'Init()'? – dwerner

+0

Cos'è 'command' nel punto in cui si ottiene l'eccezione? Dai un'occhiata qui. I punti di interruzione sono utili per esaminare lo stato prima che si verifichi l'eccezione ... – dwerner

risposta

6

Ho notato che apri le connessioni, ma non le chiudi quando hai finito con loro. Preferisco l'approccio di aprire le connessioni quando sono necessarie, piuttosto che aprirle se non sono già aperte. Potrebbero essere stantii.

Cache la stringa di connessione ma non la connessione stessa.

public static string ConnectionString {get;set;} 

public static bool InsertRecord(sql) 
{ 
    bool success = false; 
    using (var con = new Connection(ConnectionString)){ 
     var command = new SqlCommand(sql,con); 
     success = (command.ExecuteNonQuery() > 0); 
    } 
    return success; 
} 

Le risorse devono essere liberate quando non sono più necessarie.

+0

Sì, questo è ovviamente un approccio migliore. Ho cambiato i miei metodi in base al tuo suggerimento, e le eccezioni sono sparite. Per adesso. :) Grazie mille! – magic

+0

Prego! – dwerner

2

Suggerisco di controllare la segnalazione di bug this riguardante questo problema.

+0

timeout di comando predefinito = 3600; – dwerner

+1

@Mikhail Preyskurantov: Grazie per il tuo suggerimento, ma, ad esempio, mi stai dirigendo, il ragazzo ha in alcune delle eccezioni interne messaggio: "" Timeout scaduto. Il periodo di timeout trascorso prima del completamento dell'operazione o il server è non risponde. " Non ho quel messaggio nella traccia dello stack. Infine, ho aggiunto il timeout del comando nella mia stringa di connessione, ma la situazione è sempre la stessa. – magic

1

MySQL utilizza diverse variabili di timeout a diversi livelli.

momento dell'instaurazione di connessione ->connect_timeout

Quando server attende inattivo per un'altra query da inviare ->wait_timeout

Se la query viene letto o set di risultati viene inviato indietro - >net_read_timeout e net_write_timeout

Sia net_write_timeout e net_read_timeout sono se variabili di livello ssion, così puoi semplicemente cambiarle per connessioni quando sai che la query sarà problematica e quindi non interesserà il resto del server. (Come una soluzione)

Ma in primo luogo, si dovrebbe controlli il valore di default per ciascuno di questi valori di timeout sul server eseguendo qualcosa del tipo:

show variables like '%timeout%' 

Si dovrebbe anche guardare il comando che si sta inserendo e vedere se può essere semplificato o suddiviso in aggiornamenti più piccoli.

+0

Questi sono i miei valori: net_read_timeout net_write_timeout Quindi, significa che il timeout di lettura è di 30 secondi? La mia query è in effetti molto semplice, sto inserendo record nella tabella con 4 colonne. – magic

+0

sì, sembra così ^^ Corrisponde al tempo necessario per bloccarsi? prova 'SET @@ session.net_read_timeout = 360;' prima della query di inserimento, se questo è il caso. – Kharaone

+0

No, si blocca quasi immediatamente, quindi non penso che l'aumento di questo timeout aiuterà. – magic