Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SqlDataAdapter 调用fill()之前设置了 DataTableMapping为什么会有异常产生?

13 views
Skip to first unread message

tyrbl

unread,
Aug 27, 2007, 9:14:02 PM8/27/07
to
有如下代码:
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommand com = cn.CreateCommand();
com.CommandText = "select top 5 * from T_STUDENT;SELECT * FROM STUDENT_SCORE";
DataTableMapping myMapping = adapter.TableMappings.Add("T_STUDENT",
"ChildTable");
adapter.TableMappings.Add("STUDENT_SCORE", "score");
myMapping.ColumnMappings.Add("STUDENT_NAME", "NAME");
myMapping.ColumnMappings.Add("STUDENT_ID", "STUDENT_ID");
myMapping.ColumnMappings.Add("STUDENT_DOB",
"STUDENT_DOB");
myMapping.ColumnMappings.Add("STUDENT_GENDER",
"STUDENT_GENDER");
adapter.FillSchema(ds.Tables[0], SchemaType.Mapped);
adapter.MissingMappingAction = MissingMappingAction.Error;

adapter.Fill(ds); //会在adapter_FillError()引发异常

我定义了
static void adapter_FillError(object sender, FillErrorEventArgs e) {
if (e.Errors!=null)
{
e.Continue = true;
Console.WriteLine(e.Values[0]);
// 此处抛出异常 Index was outside the bounds of the array.
}
}

我想请教一下:为什么会有异常抛出。
我把adapter.MissingMappingAction =
MissingMappingAction.Error;注释掉后没有异常抛出,ds中不会有新表出现,但数据库中的信息不会加载到ds中已经存在的表中去.
如何将数据库中的信息加载到dataSet中去?

v-l...@prcvap.microsoft.com

unread,
Aug 29, 2007, 4:56:24 AM8/29/07
to
你好,

首先,你的代码似乎给的不完整。其中"adapter.FillSchema(ds.Tables[0], SchemaType.Mapped); ",你要保证ds中有DataTable才可以。

在你设置SqlDataAdapter.MissingMappingAction属性为Error后,调用Fill方法时要求源表和目标表之间必须有映射,并且源表中的字段也都有映射。SqlDataAdapter.Fill(DataSet)方法默认填充结果集名为Table的DataTable中,而之前你并未添加从Table到目标表的映射。这就是你的代码会抛异常的原因。

解决问题的办法是调用SqlDataAdapter.Fill(DataSet,string)方法,即指定一个sourceTable,例如:adapter.Fill(ds,"T_STUDENT");

另外你的代码中SqlCommand的CommandText中包含两个select语句,所以会返回两个结果集。若调用adapter.Fill(ds,"T_STUDENT")后,第一个结果集映射并填充到名为ChildTable的DataTable中,第二个结果集默认会填充到名为T_STUDENT1的DataTable中,所以你还需建立一个从T_STUDENT1到一个目标表的映射。我看到你为adapter添加了两个TableMapping,你只需将第二个TableMapping的sourceTable改名为T_STUDENT1即可:
adapter.TableMappings.Add("T_STUDENT1", "score");
还有,你必须为这个源表中的每个字段都添加映射。

如有疑问,请继续跟帖。

刘婷
在线技术支持工程师
微软全球技术支持中心

tyrbl

unread,
Aug 29, 2007, 9:16:00 PM8/29/07
to
谢谢您详细的解释,您说道:
“看到你为adapter添加了两个TableMapping,你只需将第二个TableMapping的sourceTable改名为T_STUDENT1即可:

> adapter.TableMappings.Add("T_STUDENT1", "score");


我能否在adapter.TableMappings.Add()方法的第一个直接指定我想在DataSet中填充的表的名字,比如“score”,第二个参数是我想显示的名字,比如“成绩”。
以前我一直将源表(sourceTable)理解为数据库里的表,您能在简单的帮我讲讲sourceTable的真正含义以及mapping的机制?谢谢!!

v-l...@prcvap.microsoft.com”编写:

v-l...@prcvap.microsoft.com

unread,
Aug 29, 2007, 10:52:19 PM8/29/07
to
你好,

此处的sourceTable并不是指数据库中的表名。它指的是调用Fill方法是你指定的要填充的表名。

比如数据库中有一个表叫DBTableA。你调用SqlDataAdapter.Fill方法时指定的参数为(ds, "TableA")--其中TableA就是sourceTable, 如果SqlDataAdapter中没有TableA到另一个表名的映射,那么结果是在ds中创建一个名为TableA的DataTable, 并且返回的结果集会填充在这个TableA中;如果SqlDataAdapter中有一个TableA到另一个表名的映射,例如score, 那么结果是在ds中创建一个名为score的DataTable, 并且返回的结果集会填充到这个score中。

如果你调用Fill方法是没有指定第二个参数,那么返回的结果集会填充到名为Table的DataTable中。

如果你在调用Fill方法前指定了SqlDataAdapter.MissingMappingAction属性为Error, 那么就要求在调用Fill方法填充数据时必须有映射--对于指定了sourceTable的情况,必须有sourceTable到另一个表名的映射;对于没有指定sourceTable的情况,必须有Table到另一个表名的映射。

希望我已经解释清楚了。
如还有疑问,请继续跟帖。

刘婷

tyrbl

unread,
Aug 30, 2007, 1:08:01 AM8/30/07
to
您的回答很清楚,这个问题我已经解决了,谢谢!


v-l...@prcvap.microsoft.com”编写:

0 new messages