分享
 
 
 

SqlDataAdapter中的Fill方法(2)

王朝mssql·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

上一篇中我们可以看出Fill方法最后都调用FillFromCommand和FillFromReader方法。

那我们接着探讨FillFromCommand方法

private int FillFromCommand(object data, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior)

{

IDbConnection connection1 = DbDataAdapter.GetConnection(command, "Fill");//返回connection

ConnectionState state1 = ConnectionState.Open;

if (MissingSchemaAction.AddWithKey == base.MissingSchemaAction)

//添加必需的列和主键信息以完成架构。

{

behavior |= CommandBehavior.KeyInfo;

}

int num1 = 0;

try

{

try

{

DbDataAdapter.QuietOpen(connection1, out state1);//打开连接

using (IDataReader reader1 = command.ExecuteReader(behavior | CommandBehavior.SequentialAccess))//读取数据

{

if (data is DataTable)

{

num1 = this.Fill((DataTable) data, reader1);//这个方法我们已经

//说过它最后调用FillFromReader(dataTable, null, dataReader, 0, 0, null, null);

}

else

{

num1 = this.Fill((DataSet) data, srcTable, reader1, startRecord, maxRecords);

//这个方法最后调用 return this.FillFromReader(dataSet, srcTable, dataReader,

//startRecord, maxRecords, null, null);

}

}

}

finally

{

DbDataAdapter.QuietClose(connection1, state1);//关闭连接

}

}

catch

{

throw;

}

return num1;

}

这是就不难看出FillFromCommand其实也是在调用了FillFromReader,也就是说Fill方法的所有操作将由FillFromReader方法来完成。

看看FillFromReader方法:

internal int FillFromReader(object data, string srcTable, IDataReader dataReader, int startRecord, int maxRecords, DataColumn parentChapterColumn, object parentChapterValue)

{

int num1 = 0;

int num2 = 0;//schemaCount

Label_0004:

if (0 < dataReader.FieldCount)

{

SchemaMapping mapping1 = this.FillSchemaMappingTry(data, srcTable, dataReader, num2, parentChapterColumn, parentChapterValue);//创建结构映射

num2++;

if (((mapping1 != null) && (mapping1.DataValues != null)) && (mapping1.DataTable != null))

{

try

{

mapping1.DataTable.BeginLoadData();//加载数据时关闭通知、索引维护和约束

try

{

if ((1 == num2) && ((0 < startRecord) || (0 < maxRecords)))

{

num1 = this.FillLoadDataRowChunk(mapping1, startRecord, maxRecords);//填充从

//startRecord开始的maxRecords条记录,并返回记录个数

}

else

{

int num3 = this.FillLoadDataRow(mapping1);//填充数据

if (1 == num2)

{

num1 = num3;

}

}

}

finally

{

mapping1.DataTable.EndLoadData();//数据加载后打开通知、索引维护和约束。

}

}

catch

{

throw;

}

}

}

if (!this.FillNextResult(dataReader))//判断dataReader中是否还有记录

{

return num1;

}

goto Label_0004;

}

其实到这里我们已经对fill有个总体了解,首先不管fill重载多少次它都是最后调用FillFromReader方法,在FillFromReader中先创建结构映射,然后填充数据。

接着看看结构影射,这个很复杂,请朋友们多多指教。

//结构影射

private SchemaMapping FillSchemaMappingTry(object data, string srcTable, IDataReader dataReader, int schemaCount, DataColumn parentChapterColumn, object parentChapterValue)

{

SchemaMapping mapping1 = null;

if (this.hasFillErrorHandler)

{

try

{

mapping1 = this.FillSchemaMapping(data, srcTable, dataReader, schemaCount, parentChapterColumn, parentChapterValue);

}

catch (Exception exception1)

{

this.FillErrorHandler(exception1, null, null);

}

}

else

{

mapping1 = this.FillSchemaMapping(data, srcTable, dataReader, schemaCount, parentChapterColumn, parentChapterValue);

}

return mapping1;

}

//FillSchemaMapping

private SchemaMapping FillSchemaMapping(object data, string srcTable, IDataReader dataReader, int schemaCount, DataColumn parentChapterColumn, object parentChapterValue)

{

SchemaMapping mapping1 = new SchemaMapping(this, dataReader, MissingSchemaAction.AddWithKey == base.MissingSchemaAction);//创建SchemaMapping实例

//成员名称 说明

//MissingSchemaAction:

// Add 添加必需的列以完成架构。

// AddWithKey 添加必需的列和主键信息以完成架构。有关如何将主键信息添加到 DataTable 的更多信息,请参见 FillSchema。

// Error 如果缺少指定的列映射,则生成 InvalidOperationException。

// Ignore 忽略额外列。

string text1 = null;

if (data is DataTable)

{

mapping1.DataTable = (DataTable) data;

}

else

{

mapping1.DataSet = (DataSet) data;

text1 = DbDataAdapter.GetSourceTableName(srcTable, schemaCount);//DataSet中要创建表的名称

/**

*internal static string GetSourceTableName(string srcTable, int index)

*{

* if (index == 0)

* {

* return srcTable;

*}

* return (srcTable + index.ToString());

* }

**/

}

mapping1.SetupSchema(SchemaType.Mapped, text1, true, parentChapterColumn, parentChapterValue);//

/*

*

* public enum SchemaType

*{

* // Fields

* Mapped = 2, 将任何现有的表映射应用到传入架构,用转换的架构配置 DataSet。

* Source = 1 忽略 DataAdapter 上的任何表映射。使用传入架构配置 DataSet,而不应用任何转换。

* }

**/

return mapping1;

}

//SchemaMapping

internal SchemaMapping(DbDataAdapter adapter, IDataReader dataReader, bool keyInfo)

{

this.adapter = adapter;

this.dataReader = dataReader;

if (keyInfo)//如果必须添加列和主键,就用dataReader的GetSchemaTable()返回一个DataTable

{

this.schemaTable = dataReader.GetSchemaTable();//返回一个 DataTable,它描述 SqlDataReader 的列元数据。可以查看msdn

}

}

//SetupSchema 创建

internal void SetupSchema(SchemaType schemaType, string sourceTableName, bool gettingData, DataColumn parentChapterColumn, object parentChapterValue)

{

MissingMappingAction action1;

MissingSchemaAction action2;

if (SchemaType.Mapped == schemaType)

{

action1 = this.adapter.MissingMappingAction;//确定传入数据没有匹配的表或列时需要执行的操作

action2 = this.adapter.MissingSchemaAction;//确定现有 DataSet 架构与传入数据不匹配时需要执行的操作。

if (!ADP.IsEmpty(sourceTableName))

{

this.tableMapping = this.adapter.GetTableMappingBySchemaAction(sourceTableName, sourceTableName, action1);//创建源表和 DataTable 之间的主映射。

goto Label_016D;

}

if (this.dataTable == null)

{

goto Label_016D;

}

int num1 = this.adapter.IndexOfDataSetTable(this.dataTable.TableName);

if (-1 != num1)

{

this.tableMapping = this.adapter.TableMappings[num1];

goto Label_016D;

}

switch (action1)

{

case MissingMappingAction.Passthrough://创建源列或源表,并使用其原始名称将其添加到 DataSet。

{

this.tableMapping = new DataTableMapping(this.dataTable.TableName, this.dataTable.TableName);

goto Label_016D;

}

case MissingMappingAction.Ignore://忽略没有映射的列或表。

{

this.tableMapping = null;

goto Label_016D;

}

case MissingMappingAction.Error://缺少指定的列映射,则生成 InvalidOperationException

{

throw ADP.MissingTableMappingDestination(this.dataTable.TableName);

}

}

throw ADP.InvalidMappingAction((int) action1);

}

if (SchemaType.Source != schemaType)

{

throw ADP.InvalidSchemaType((int) schemaType);

}

action1 = MissingMappingAction.Passthrough;

action2 = MissingSchemaAction.Add;

if (!ADP.IsEmpty(sourceTableName))

{

this.tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction(null, sourceTableName, sourceTableName, action1);

}

else if (this.dataTable != null)

{

int num2 = this.adapter.IndexOfDataSetTable(this.dataTable.TableName);

if (-1 != num2)

{

this.tableMapping = this.adapter.TableMappings[num2];

}

else

{

this.tableMapping = new DataTableMapping(this.dataTable.TableName, this.dataTable.TableName);////创建源表和 DataTable 之间的主映射。

}

}

Label_016D:

if (this.tableMapping != null)

{

if (this.dataTable == null)

{

this.dataTable = this.tableMapping.GetDataTableBySchemaAction(this.dataSet, action2);使用action2的 值获取DataSet的当前 DataTable。可以查看msdn

if (this.dataTable == null)

{

return;

}

}

if (this.schemaTable == null)

{

this.SetupSchemaWithoutKeyInfo(action1, action2, gettingData, parentChapterColumn, parentChapterValue);

}

else

{

this.SetupSchemaWithKeyInfo(action1, action2, gettingData, parentChapterColumn, parentChapterValue);

}

}

}

//FillLoadDataRowChunk

private int FillLoadDataRowChunk(SchemaMapping mapping, int startRecord, int maxRecords)

{

IDataReader reader1 = mapping.DataReader;

while (0 < startRecord) //把DataReader调整到读startRecord记录的位置

{ //如果DataReader的总的记录数小于startRecord,就返回0

if (!reader1.Read()) //其实在这里也可以看出要在DataReader中定位,只有去边历DataReader

{ //到这里我们也可以明白fill方法其实也是用DataReader一条条读出来的

return 0;

}

startRecord--;

}

int num1 = 0;

if (0 >= maxRecords)

{

goto Label_0062;

}

bool flag1 = base.AcceptChangesDuringFill;//指示在Fill操作过程中,在将 AcceptChanges 添加到 DataTable 之后是否针对 DataRow 调用它。可以在msdn中的DataAdapter 类中查看

goto Label_0054;

Label_002B:

try

{

mapping.LoadDataRow(this.hasFillErrorHandler, flag1);//装载数据

num1++;

}

catch (Exception exception1)

{

this.FillErrorHandler(exception1, mapping.DataTable, mapping.DataValues);

}

Label_0054:

if (num1 >= maxRecords)//如果载入的记录数已经满足条件,就退出,否则继续

{

goto Label_006A;

}

if (reader1.Read())//继续读取数据

{

goto Label_002B;

}

goto Label_006A;

Label_0062:

num1 = this.FillLoadDataRow(mapping);

Label_006A:

return num1;

}

到这里fill方法大概就完了,其实看来fill方法就是首先创建映射,然后在用datareader把数据填充进来.其中我忽略了好多东西比如它的异常处理,还有好多细节,请各位朋友多多指教,在这里列出来也是和各位朋友探讨。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有