Чтение из IDbCommand с использованием унаследованного пользовательского IDataReader

Я сделал пользовательский класс наследует IDataReader и успешно реализовали пользовательский ServerWriter sqlBulkCopy с пользовательским классом, который использует объект C# вместо DataTable,

Это оказалось более эффективным подходом, как я и подозревал.

Сейчас пытаюсь Read и у меня есть некоторые проблемы

Это 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;
   }
}

Объект отображается точно так же, как его соответствующий SqlTable.

Настройка SqlCommand чтобы ExecuteReader() на моем пользовательском IDataReader не работал, поэтому я попытался с IDbCommand который тогда это действительно компилировало, но все еще, пытаясь прочитать, я получаю ошибку:

Невозможно привести объект типа "System.Data.SqlClient.SqlDataReader" к типу "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())
{

}

Как написать на сервер это работает, как я могу реализовать это правильно с Read ?

ОБНОВИТЬ

Еще немного о моих модулях

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; }
}

1 ответ

Краткий ответ: вы не можете изменить тип, возвращаемый SqlCommand.ExecuteReader() ,

Это всегда будет примером SqlDataReader,

Различные решения:

1 Оберните вещи там, где это имеет смысл для вас.

Если вы идете до крайности, напишите свой IDbProviderFactory это оборачивает SqlConnection со своим собственным подключением, командой и классом чтения данных.

Например, именно это и делает Miniprofiler для обработки всех запросов SQL и сбора времени выполнения, количества строк и т. Д. Исходный код

Или вы можете обернуть только читателя каким-то методом расширения, например так: sqlCmd.ExecuteReader().AsMyReader(), Какие AsMyReader() будет сделать, это вернуть обычай IDataReader что делает ваши вещи и делегаты к фактическому SqlDataReader,

2 Используйте существующие вспомогательные библиотеки

Я не совсем уверен, чего вы пытаетесь достичь при чтении материала, но в этом пространстве есть хорошие библиотеки. Не нужно придумывать свои собственные решения.

FastMember ( Nuget) позволяет создавать IDataReader интерфейсы вокруг любого IEnumerable<T> или же DataTable, Он сделан для того, чтобы его можно было легко использовать в качестве семени для SqlBulkCopy легко вставить данные с макс. производительность в таблице SQL Server.

Кроме того, для облегчения выполнения SQL-запросов и анализа их результатов, Dapper великолепен.

Другие вопросы по тегам