数据集更新应用新记录的默认值,而不是已设置的值

时间:2019-11-21 00:19:58

标签: .net sql-server vb.net dataset

我在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的应用程序中的所有其他代码都可以继续正常工作(或多或少,尽管我认为此问题可能会在其他区域出现,但对用户的可见性较小)。

关于什么可能导致这种情况的任何建议?

1 个答案:

答案 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传递到记录级别。