2015-11-29 12 views
10

Ich habe eine benutzerdefinierte Klasse erbt IDataReader gemacht und habe erfolgreich umgesetzt einen benutzerdefinierte ServerWriter sqlBulkCopy mit der benutzerdefinierten Klasse, die ein C# Objekt statt DataTable verwendet.von IDbCommand Lesen IDataReader eine vererbte Gewohnheit mit

Das erwies sich als ein effizienter Ansatz, wie ich vermutete.

Jetzt versuche ich zu Read und ich habe einige Probleme

Dies ist IDataReader:

// get Server Data Table Object IDataReader 
public class GetSDTOIDataReaderM : IDataReader 
{ 
    //private IEnumerator<MyTestObject> enumerator = null; 

    public MySqlDbTableObject.Raw.SqlDbTableM propSqlTbl { get; set; } 

    // implementing relevant GetValue(), filedCount() and Read() 
    // this is how I did with WriteToServer 
    public bool Read() 
    { 
     return ++this.ReaderRowsCount < this.propSqlTbl.Table.ElementAt(0).Row.Count; 
    } 
} 

Das Objekt abgebildet wird, genau wie seine entsprach SQLTable.

Einstellung ein SqlCommand zu ExecuteReader() auf meiner benutzerdefinierten IDataReader nicht so funktionierten Ich habe mit IDbCommand versucht, die dann kam es kompilieren, aber immer noch, wenn sie versuchen zu lesen bekomme ich einen Fehler:

Unable to cast object of type 'System.Data.SqlClient.SqlDataReader' to type 'GetSDTOIDataReaderM'

this.propComunicator.AsGetSDTOCom().SqlCmd.Connection.Open(); 
//this is the line of the error 
using (this.propComunicator.AsGetSDTOCom().SDTOIDataReader = (Raw.Comunicator.Raw.GetSDTOIDataReaderM)this.propComunicator.AsGetSDTOCom().SqlCmd.ExecuteReader()) 
{ 

} 

Wie schreiben zum Server hat es funktioniert, Wie kann ich es richtig mit Read implementieren?

UPDATE

ein wenig mehr über meine Module

public class TransManSF 
{ 
    public enum CommunicatorTypeS { Reader, Adapter, GetSDTOReaderA, SqlBcpyIDataReaderM }; 
    public enum DbIntreactorTypeS { TableObject, TableRowObject, Sproc, SqlCmd }; 
    public enum SqlCmdActionS { NotSet, SELECT, INSERT, UPDATE, DROP }; 
    public enum SqlCmdStrSelModeS { Single, RecentEfected, count, All, Top10, Top100, Top1000 }; 
    public enum SqlCmdStrSelOrderByS { NotSet = 0, Asc = 1, Desc = 2 }; 
    public enum SqlCmdStrSetterModeS { Single, Multi}; 
    public enum STDOTypeS { NotSet, ServerWriter, ServerTableGetter, ServerBiDerctional } 
    public enum SprocTypeS { Sproc, TvPSrpoc } 
    public enum TransExecActionTypeS { WriteToServer, GetTable } 
} 

public static TransMan.Raw.ComunicatorCLF.BulkCopyComSCL AsBulkCopyCom(this TransMan.Raw.ComunicatorCLF.ComunicatorM SelfCom) 
{ 
    return (TransMan.Raw.ComunicatorCLF.BulkCopyComSCL)SelfCom; 
} 

virtual public void ExecuteTransaction(AppMods.DataBase.TransManSF.TransExecActionTypeS parSelectedTransType, TransManSF.SqlCmdStrSelOrderByS parExecOrderByS, int OrderByOrdinal = 0) 
{ 
    if (parSelectedTransType == AppMods.DataBase.TransManSF.TransExecActionTypeS.WriteToServer) 
     using (this.propComunicator.AsBulkCopyCom().Conn) 
     { 
      this.propComunicator.AsBulkCopyCom().Conn.Open(); 
      using (var IDRdrServerWriter = this.propComunicator.AsBulkCopyCom().ServerWriter) 
      { 
       var Eng = this.propExecuter.AsBulkCopyExec().Engine; 
       Eng.BulkCopyTimeout = 240; 
       Eng.WriteToServer(IDRdrServerWriter); 

      } 
      this.propComunicator.AsBulkCopyCom().Conn.Close(); 
     } 
    else if (parSelectedTransType == AppMods.DataBase.TransManSF.TransExecActionTypeS.GetTable) 
    { 
     var DreaderCom = this.propComunicator.AsDReaderCom(); 
     using (DreaderCom.SqlCmd.Connection) 
     { 
      DreaderCom.SqlCmd.Connection.Open(); 
      using (DreaderCom.Driver = DreaderCom.SqlCmd.ExecuteReader()) 
      { 
       if (DreaderCom.Driver.HasRows) while (DreaderCom.Driver.Read()) 
        { 
         for (int i = 0; i < DreaderCom.Driver.FieldCount; i++) 
         { 
          var CurRdrColumn = DreaderCom.Driver.GetValue(i); 
          this.Table[i, 0] = CurRdrColumn; 
         } 
        } 
      } 
      DreaderCom.SqlCmd.Connection.Close(); 
     }       
    } 
} 


public struct customComConfgBulkCopyA 
{ 
     public TransManSF.CommunicatorTypeS ComType; 
     public customComConfgBulkCopyA(TransManSF.CommunicatorTypeS ctrComType = TransManSF.CommunicatorTypeS.SqlBcpyIDataReaderM) 
     { 
      this.ComType = ctrComType; 
     } 
} 
public sealed class BulkCopyComSCL :CustomComA 
{ 
    public new Configurations.comunicator.customComConfgBulkCopyA Meta; 
    public SqlConnection Conn { get; set; } 
    public Raw.SqlBcpyIDataReaderM ServerWriter { get; set; } 
} 

public class SqlDbTableM : SqlDB1stTransA 
{ 
    virtual public DbSchema.Raw.TableDictionaryA TableDict { get; set; } 
    public virtual new TransMan.Raw.Configurations.SDB1stTransConfgF.SDTOMetaA Meta { get; set; } 
    virtual public Raw.ColumnSetsCollM Table { get; set; } 
    public override TransMan.Raw.ComunicatorCLF.ComunicatorM propComunicator 
    { 
     get 
     { 
       return base.propComunicator; 
     } 
     set 
     { 
       base.propComunicator = value; 
     } 
    } 
    public override TransMan.Raw.Executers.ExecuterM propExecuter 
    { 
     get 
     { 
      return base.propExecuter; 
     } 
     set 
     { 
      base.propExecuter = value; 
     } 
    } 
    public SqlDbTableM(TransManSF.STDOTypeS ctrTransType) 
      : base(TransManSF.DbIntreactorTypeS.TableObject) { } 
} 

public sealed class GetSDTOComSCL : CustomComA 
{ 
    public new Configurations.comunicator.customComConfgGetSDTOReaderA Meta; 
    public new IDbCommand SqlCmd; 
    public Raw.GetSDTOIDataReaderM SDTOIDataReader { get; set; } 
} 
+0

Was gibt propComunicator.AsGetSDTOCom() zurück? Ist das eine Klasse, die Sie in die Finger bekommen können? – RePierre

+0

@RePierre ja sicher werde ich ein Update hinzufügen 5 Minuten –

+0

@RePierre Wenn es mehr Informationen benötigt, werde ich gerne erklären und teilen Entschuldigung, es dauerte 25 Minuten –

Antwort

6

Kurze Antwort: Sie können nicht die Art von SqlCommand.ExecuteReader() zurück ändern.

Es wird immer eine Instanz von SqlDataReader sein.

Verschiedene Lösungen:

1 Wrap Dinge, wo es Sinn macht für Sie.

Wenn Sie bis zum Äußersten gehen, schreiben Sie Ihre eigene IDbProviderFactory, die eine SqlConnection mit einer eigenen Verbindung, Befehl und Datenleseklasse umschließt.

Zum Beispiel ist das, was Miniprofiler zum Instrument macht alle Anfragen SQL und sammeln mit irgendeiner Art von Erweiterungsmethode Ausführungszeiten, Anzahl der Zeilen usw. Source code

Oder Sie können einfach den Leser wickeln, etwa so: sqlCmd.ExecuteReader().AsMyReader() . Was AsMyReader() tun würde, ist eine benutzerdefinierte IDataReader, die Ihre Sachen und Delegierten auf die tatsächliche SqlDataReader zurückgibt.

2 Verwenden vorhandene Hilfsbibliotheken

Ich bin nicht ganz sicher, was Sie versuchen, Sachen zu erreichen, wenn das Lesen, aber es gibt gute Bibliotheken in diesem Raum. Keine Notwendigkeit, eigene Lösungen zu finden.

FastMember (Nuget) ermöglicht IDataReader Schnittstellen um jede IEnumerable<T> oder DataTable zu schaffen. Es ist so gemacht, dass es leicht als Seed zu SqlBulkCopy verwendet werden kann, um Daten mit max. Leistung in eine SQL Server-Tabelle.

Auch, um die Ausführung von SQL-Abfragen und die Analyse ihrer Ergebnisse zu erleichtern, ist Dapper genial.

+0

mit Blick auf den ersten Link der benutzerdefinierte 'DbCommand' ist der Beginn eines Kerns einer Lösung? Wenn ich das als Befehl verwende, wird es das benutzerdefinierte "IDataReader" leichter machen? 'public class ProfiledDbCommand: DbCommand, ICloneable' –

+0

Nein, der Anfang von allem ist' DbProviderFactory'. Es erstellt seine eigene 'DbConnection', die ihren eigenen' DbCommand' erstellt, der ihren eigenen 'DbDataReader' erzeugt. – jods

+0

ok, also werde ich weiter nachforschen von der Quelle 'DbProviderFactory' Vielen Dank für jetzt! –