Чтение из IDbCommand с использованием унаследованного пользовательского IDataReader
Я сделал собственный класс наследует IDataReader
и успешно
реализовал пользовательский ServerWriter sqlBulkCopy
с пользовательским классом, который использует объект С# вместо 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" в 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())
{
}
Как запись на сервер, он работал, , как я могу его правильно реализовать с помощью Read
?
UPDATE
Немного больше о моих модулях
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
своим собственным классом соединения, команды и datareader.
Например, что делает Miniprofiler для обработки всех запросов SQL и сбора времени выполнения, количества строк и т.д. Исходный код
Или вы можете обернуть только читателя каким-то расширением, например: sqlCmd.ExecuteReader().AsMyReader()
. То, что AsMyReader()
будет делать, это вернуть пользовательский IDataReader
, который делает ваши вещи и делегирует фактический SqlDataReader
.
2 Используйте существующие вспомогательные библиотеки
Я не совсем уверен, чего вы пытаетесь достичь при чтении, но в этом пространстве есть хорошие библиотеки. Не нужно придумывать свои собственные решения.
FastMember (Nuget) позволяет создавать IDataReader
интерфейсы вокруг любых IEnumerable<T>
или DataTable
. Это сделано для удобства использования в качестве семени SqlBulkCopy
, чтобы легко вставлять данные с макс. производительности в таблицу SQL Server.
Кроме того, чтобы облегчить выполнение SQL-запросов и анализ их результатов, Dapper является удивительным.