我在DataSet(.Net Framework 4.0)中有一个相当简单的表,称为MortgageFees。它通过MortgageID链接到父抵押表。当将新记录插入现有抵押的MortgageFees表中时,就没有问题。但是,在创建新的抵押时,在抵押已保存并具有新的ID号之后,.Net DBAdapter for MortgageFees表会写出原始记录的默认值,而不是已设置的值。在保存之前和之后查看记录的转储,将显示所有需要值的字段中都有值。但是,使用SQL跟踪工具,Insert命令写出的是原始记录的默认值。该代码已经使用了很多年,但是在保存新的抵押贷款和MortgageFees时偶尔会出现故障。
insert命令非常简单:
INSERT INTO [MortgageFees] ([MortgageID], [ApplicationID], [ConstructionDrawID], [CompanyID], [TransactionTypeID], [Rate], [Amount], [ToInvestorRate], [ToInvestorAmount], [BrokerName], [BrokerContactID], [Memo], [SortOrder], [UsedForAPRCalculation], [DeductFromPrincipal], [UseForNewMortgages], [UseForRenewedMortgages]) VALUES (@MortgageID, @ApplicationID, @ConstructionDrawID, @CompanyID, @TransactionTypeID, @Rate, @Amount, @ToInvestorRate, @ToInvestorAmount, @BrokerName, @BrokerContactID, @Memo, @SortOrder, @UsedForAPRCalculation, @DeductFromPrincipal, @UseForNewMortgages, @UseForRenewedMortgages);
SELECT MortgageFeeID, MortgageID, ApplicationID, ConstructionDrawID, CompanyID, TransactionTypeID, Rate, Amount, ToInvestorRate, ToInvestorAmount, BrokerName, BrokerContactID, Memo, SortOrder, UsedForAPRCalculation, DeductFromPrincipal, UseForNewMortgages, UseForRenewedMortgages, Version FROM MortgageFees WHERE (MortgageFeeID = SCOPE_IDENTITY()) ORDER BY SortOrder, Amount DESC
此代码是由DataSet编辑器生成的,尚未被我修改。记录的转储显示以下内容(请注意TransactionTypeID有一个值,然后RowError声明没有):
{Armada.BusinessComponents.dsEditMortgage.MortgageFeesRow}
_action: Nothing {0}
_columns: {System.Data.DataColumnCollection}
_countColumnChange: 6
_element: Nothing
_lastChangedColumn: {MortgageID}
_objectTypeCount: 1723
_rbTreeNodeId: 1
_rowID: 1
_table: {MortgageFees}
Amount: 375D
ApplicationID: DBNull
BrokerContactID: DBNull
BrokerName: DBNull
CompaniesRow: Nothing
CompanyID: DBNull
ConstructionDrawID: DBNull
ConstructionDrawsRow: Nothing
DeductFromPrincipal: False
Element: Nothing
error: {System.Data.DataError}
HasErrors: True
HasPropertyChanged: True
.
.
.
Memo: DBNull
MortgageApplicationRow: Nothing
MortgageFeeID: -1
MortgageID: 857
MORTGAGESRow: {Armada.BusinessComponents.dsEditMortgage.MORTGAGESRow}
newRecord: 0
ObjectID: 1722
oldRecord: -1
Rate: 0.75D
RBTreeNodeId: 1
RowError: "Cannot insert the value NULL into column 'TransactionTypeID', table 'ArmadaDev.dbo.MortgageFees'; column does not allow nulls. INSERT fails. The statement has been terminated."
rowID: 1
RowState: Added {4}
SortOrder: 1
Table: {MortgageFees}
tableMortgageFees: {MortgageFees}
tempRecord: 1
ToInvestorAmount: 375D
ToInvestorRate: 100D
TransactionTypeID: 8
TX_TYPESRow: {Armada.BusinessComponents.dsEditMortgage.TX_TYPESRow}
UsedForAPRCalculation: False
UseForNewMortgages: False
UseForRenewedMortgages: False
上面的转储是在适配器上运行Update方法之后进行的。同时使用SQL跟踪工具时,它显示发出以下SQL:
exec sp_executesql N'INSERT INTO [MortgageFees] ([MortgageID], [ApplicationID], [ConstructionDrawID], [CompanyID], [TransactionTypeID], [Rate], [Amount], [ToInvestorRate], [ToInvestorAmount], [BrokerName], [BrokerContactID], [Memo], [SortOrder], [UsedForAPRCalculation], [DeductFromPrincipal], [UseForNewMortgages], [UseForRenewedMortgages]) VALUES (@MortgageID, @ApplicationID, @ConstructionDrawID, @CompanyID, @TransactionTypeID, @Rate, @Amount, @ToInvestorRate, @ToInvestorAmount, @BrokerName, @BrokerContactID, @Memo, @SortOrder, @UsedForAPRCalculation, @DeductFromPrincipal, @UseForNewMortgages, @UseForRenewedMortgages);
SELECT MortgageFeeID, MortgageID, ApplicationID, ConstructionDrawID, CompanyID, TransactionTypeID, Rate, Amount, ToInvestorRate, ToInvestorAmount, BrokerName, BrokerContactID, Memo, SortOrder, UsedForAPRCalculation, DeductFromPrincipal, UseForNewMortgages, UseForRenewedMortgages, Version FROM MortgageFees WHERE (MortgageFeeID = SCOPE_IDENTITY()) ORDER BY SortOrder, Amount DESC',
N'@MortgageID int,@ApplicationID int,@ConstructionDrawID int,@CompanyID int,@TransactionTypeID int,@Rate decimal(6,3),@Amount money,@ToInvestorRate decimal(6,3),@ToInvestorAmount money,@BrokerName nvarchar(4000),@BrokerContactID int,@Memo nvarchar(4000),@SortOrder tinyint,@UsedForAPRCalculation bit,@DeductFromPrincipal bit,@UseForNewMortgages bit,@UseForRenewedMortgages bit',
@MortgageID=-1,@ApplicationID=NULL,@ConstructionDrawID=NULL,@CompanyID=NULL,
@TransactionTypeID=NULL,@Rate=NULL,@Amount=$0.0000,@ToInvestorRate=NULL,@ToInvestorAmount=$0.0000,@BrokerName=NULL,@BrokerContactID=NULL,@Memo=NULL,@SortOrder=1,@UsedForAPRCalculation=0,@DeductFromPrincipal=0,@UseForNewMortgages=0,@UseForRenewedMortgages=0
如您所见,发布给命令的值与记录中的值不匹配。适配器中的命令是使用数据集设计器中表上的“更新”方法设置的。使用DataSet的应用程序中的所有其他代码都可以继续正常工作(或多或少,尽管我认为此问题可能会在其他区域出现,但对用户的可见性较小)。
关于什么可能导致这种情况的任何建议?
答案 0 :(得分:0)
原来的问题是,仅在DataGridView和基础BindingSource上调用EndEdit是不够的。我添加了一个扩展函数,该函数遍历DataTable的所有行并调用EndEdit。这将迫使未保存的更改生效。现在的代码如下所示:
grdMortgageFees.EndEdit() ' force this, again, just in case
bsMortgageFees.EndEdit() ' And push it down from the Binding Source
Me.DsEditMortgage1.MortgageFees.MarkAsEdited() ' Now mark the records as edited
cnt += Me.DsEditMortgage1.MortgageFees.Save(dbConnection) ' and save the changes.
扩展功能很简单,看起来像这样:
''' <summary>
''' Apply EndEdit to all of the rows in a table.
''' </summary>
''' <param name="Table">DataTable to apply this method to.</param>
''' <remarks></remarks>
<Extension()>
Public Sub MarkAsEdited(Table As DataTable)
For Each row As DataRow In Table.Rows
row.EndEdit()
Next
End Sub
我仍然相信底层Microsoft .net框架代码中可能存在一个错误,而BindingSource中可能似乎没有将EndEdit传递到记录级别。