主数据表与明细数据表的问题

时间:2022-02-24 03:30:36
我设计了一个订单(或者叫销货单),数据表分为主表与明细表,窗体上分别用datatimepicker控件、combobox控件与textbox控件来做为主表的“日期”、“客户”与“订单编号”,又用datagrid控件来显示明细表,(明细表字段有:订单编号、产品编号、数量、单价、金额),主表与明细表以“订单编号”来产生关联。经编译在实际使用时,输入完主表的内容,明细表在输入完第一笔记录转入下一等记录时,系统提示:“订单编号不能为空,是否修正“,也就是说明细表的”订单编号“没有因关联自动生成相应的值。因本人属初学,不知如何解决此问题,多谢指教!

10 个解决方案

#1


听你所述感觉你更像个用户而不是程序员.

可以将你的关键代码贴上来, 否则帮不了你.

#2


厉害呀“马客”,俺虽不是一个用户,但差不多,刚刚接触“编程”这个东西,而且设计的这一个订单程序是完全参考有关书籍来完成的,废话俺也不想多说,但愿在俺的努力下以后不再这么差劲。
'SqlConnection,DataSet,SqlDataAdapter均在可视化方式下建立的,名称分别为:“cnTest,dsTest,daOrders(连接订单主数据表),daOrderDetails(连接订单明细表),daCustomer(连接客户表)”,以下为相关代码,俺尽量能详细说明,也不知能否看的明白?


'在Public区定义的变量
    '建立dtOrderDetails对象, 利用它的ColumnChanged事件来计算金额
    Dim WithEvents dtOrderDetails As New DataTable()
    '管理Orders的记录
    Dim BmOrders As BindingManagerBase
    '管理OrderDetails的记录
    Dim BmOrderDetails As BindingManagerBase
    '是否要计算金额的标志
    Dim OrderDetailsHasChange As Boolean
    '建立字段对象-小计, 用来指定新建时的默认值
    Dim SubTotal As DataColumn
    '建立字段对象-税额, 用来指定新建时的默认值
    Dim Tax As DataColumn
    '建立字段对象-总计, 用来指定新建时的默认值
    Dim Amount As DataColumn
    '建立字段对象-数量, 用来指定新建时的默认值
    Dim Quantity As DataColumn
    '建立字段对象-单价, 用来指定新建时的默认值
    Dim UnitPrice As DataColumn




    Private Sub bnFirst_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnFirst.Click
        '首笔记录
        BmOrders.Position = 0
    End Sub

    Private Sub bnPrior_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnPrior.Click
        '上一笔记录
        BmOrders.Position -= 1
    End Sub

    Private Sub bnNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnNext.Click
        '下一笔记录
        BmOrders.Position += 1
    End Sub

    Private Sub bnLast_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnLast.Click
        '末笔记录
        BmOrders.Position = BmOrders.Count - 1
    End Sub

    Private Sub bnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnAdd.Click
        Try
            '新建记录
            BmOrders.EndCurrentEdit()
            BmOrders.AddNew()
        Catch err As System.SystemException
            MessageBox.Show(err.ToString)
        End Try
    End Sub

    Private Sub bnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnDelete.Click
        '删除记录
        If BmOrders.Count > 0 Then
            BmOrders.RemoveAt(BmOrders.Position)
        End If
    End Sub

    Private Sub bnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnCancel.Click
        '取销编辑
        BmOrders.CancelCurrentEdit()
    End Sub

    Private Sub bnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnLoad.Click
        ’加载数据
        FillData()
    End Sub

    Private Sub bnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnUpdate.Click
        '更新数据
        Dim dsTestChange As DataSet
        '终止目前所有的资料异动    
        '明细先储存再储存主档
        BmOrderDetails.EndCurrentEdit()
        BmOrders.EndCurrentEdit()
        '有删除的数据吗?
        If Not dsTest.HasChanges(DataRowState.Deleted) Then
            Try
                '先更新主档再更新明细档
                daOrders.Update(dsTest, "Orders")
                daOrderDetails.Update(dsTest, "OrderDetails")
                dsTest.AcceptChanges()
            Catch err As System.SystemException
                dsTest.RejectChanges()
                MessageBox.Show(err.ToString)
                Throw
            End Try
        Else
            Try
                '先更新明细档再更新主档
                daOrderDetails.Update(dsTest, "OrderDetails")
                daOrders.Update(dsTest, "Orders")
                dsTest.AcceptChanges()
            Catch err As System.SystemException
                dsTest.RejectChanges()
                MessageBox.Show(err.ToString)
                Throw
            End Try
        End If

    End Sub

    Private Sub fmOrders_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        '先填入资料
        FillData()
        '把dtOrderDetails这个DataTable对象, 指定为dsTest里的OrderDetails
        dtOrderDetails = dsTest.Tables("OrderDetails")
        '把Orders与BmOrders做资料系结
        BmOrders = Me.BindingContext(dsTest, "Orders")
        '把OrderDetailss与BmOrderDetais做资料系结
        BmOrderDetails = Me.BindingContext(dsTest, "Orders.OrdersOrderDetails")
        '一开始, 预设是ColumnChanged事件里的计算程序代码是要执行的
        OrderDetailsHasChange = True
        '把SubTotal这个DataColumn对象, 指定为Orders里的SubTotal
        SubTotal = dsTest.Tables("Orders").Columns("SubTotal")
        SubTotal.DefaultValue = 0
        '把Tax这个DataColumn对象, 指定为Orders里的Tax
        Tax = dsTest.Tables("Orders").Columns("Tax")
        Tax.DefaultValue = 0
        '把Amount这个DataColumn对象, 指定为Orders里的Amounte
        Amount = dsTest.Tables("Orders").Columns("Amount")
        Amount.DefaultValue = 0
        '把Quantity这个DataColumn对象, 指定为OrderDetails里的Quantity
        Quantity = dsTest.Tables("OrderDetails").Columns("Quantity")
        Quantity.DefaultValue = 0
        '把UnitPrice这个DataColumn对象, 指定为OrderDetails里的UnitPrice
        UnitPrice = dsTest.Tables("OrderDetails").Columns("UnitPrice")
        UnitPrice.DefaultValue = 0

    End Sub

    Private Sub FillData()
        '关闭数据表格的条件约束
        dsTest.EnforceConstraints = False
        '填入数据集, 注意顺序
        '填入订单主文件
        daOrders.Fill(dsTest)
        '填入订单明细文件
        daOrderDetails.Fill(dsTest)
        '填入客户档
        daCustomer.Fill(dsTest)
        '打开数据表格的条件约束
        dsTest.EnforceConstraints = True

    End Sub

    Private Sub dtOrderDetails_ColumnChanged(ByVal sender As Object, ByVal e As System.Data.DataColumnChangeEventArgs) Handles dtOrderDetails.ColumnChanged
        '建立DataRow对象-Orders
        Dim drOrders As DataRow
        '建立DataRow对象-OrderDetails
        Dim drOrderDetails As DataRow
        '用来计算总数的变量
        Dim iSubTotal As Integer
        Try
            '如果为False, 就不再进去执行, 避免造成无穷回路
            If OrderDetailsHasChange Then
                '进来先变回False
                OrderDetailsHasChange = False
                '计算明细的金额
                e.Row("DetailAmount") = e.Row("Quantity") * e.Row("UnitPrice")
                '找出目前的Orders所在的记录
                drOrders = dsTest.Tables("Orders").Rows(BmOrders.Position)
                '先归0, 养成习惯, 虽然默认值就是0
                iSubTotal = 0
                '找出每笔明细出来
                For Each drOrderDetails In drOrders.GetChildRows _
                                          ("OrdersOrderDetails")
                    '金额累加
                    iSubTotal = iSubTotal + drOrderDetails("DetailAmount")
                Next
                '变为编辑模式
                drOrders.BeginEdit()
                '明细的总计金额=主档的小计
                drOrders("SubTotal") = iSubTotal
                '计算税额
                drOrders("Tax") = drOrders("SubTotal") * 0.05
                '计算总计 
                drOrders("Amount") = drOrders("SubTotal") + drOrders("Tax")
                '储存, 结束编辑
                drOrders.EndEdit()
            End If
        Finally
            '无论如何, 要把标志变回True
            OrderDetailsHasChange = True
        End Try
    End Sub

#3


是不是学生啊,如果程序要写这么多注释,那就是垃圾!

#4


俺是想把俺的思路写的尽量详细一点,好让各位高手以最快的速度指点错误,正常写程序时是不会写这么多注释的。

#5


晕, 贴了这么多上来, 找了一下, 居然没发现"订单编号不能为空,是否修正"这句话的出处..我都不知道这个出错条件的触发事件是什么你叫我怎么调试??

我一般这样处理:先找到"订单编号不能为空,是否修正"的触发事件,即什么原因导致系统提示这句话, 然后把原因一层一层深入下去.

#6


马客你好!如果你愿意的话,俺把俺的程序及数据库打包发给你,方便的话给俺留个E-mail或QQ号。

#7


可以, 有时间帮你看看吧
mark2win@163.com

#8


谢谢了,俺马上发过去!

#9


写注释是一个好习惯,存在自己思路的地方一般都要写,不然别人维护或者自己以后维护都是一件头痛的事情,这点我想资深人士会深有体会

主细档关联,采用DataGrid这种具有数据绑定功能的控件,只需要将数据源同时绑定到各个控件即可(设置DataSource)

#10


路过...
------------------------------------------------------------------------------------ 
100M.Net空间+50M企业邮局=60元/年
100M.Net空间+国际*域名=100元/年
国际*域名.com.net.cn=50元/年
本站申请域名可绑定免费10M Asp.Net空间
1000M.Net空间 + 100M MsSql数据库 + 1000M企业邮局 + *域名=600元/年
数据库 企业邮局 网站推广 整机租用 美国空间 网站建设 均有售
还有很多优惠套餐提供给各个用户层.
有意者可联系电话:021-64802212 传真:021-64802212 
咨询信箱:info@kingtoo.com 咨询OICQ:68311305,379620139 81778640 
 

#1


听你所述感觉你更像个用户而不是程序员.

可以将你的关键代码贴上来, 否则帮不了你.

#2


厉害呀“马客”,俺虽不是一个用户,但差不多,刚刚接触“编程”这个东西,而且设计的这一个订单程序是完全参考有关书籍来完成的,废话俺也不想多说,但愿在俺的努力下以后不再这么差劲。
'SqlConnection,DataSet,SqlDataAdapter均在可视化方式下建立的,名称分别为:“cnTest,dsTest,daOrders(连接订单主数据表),daOrderDetails(连接订单明细表),daCustomer(连接客户表)”,以下为相关代码,俺尽量能详细说明,也不知能否看的明白?


'在Public区定义的变量
    '建立dtOrderDetails对象, 利用它的ColumnChanged事件来计算金额
    Dim WithEvents dtOrderDetails As New DataTable()
    '管理Orders的记录
    Dim BmOrders As BindingManagerBase
    '管理OrderDetails的记录
    Dim BmOrderDetails As BindingManagerBase
    '是否要计算金额的标志
    Dim OrderDetailsHasChange As Boolean
    '建立字段对象-小计, 用来指定新建时的默认值
    Dim SubTotal As DataColumn
    '建立字段对象-税额, 用来指定新建时的默认值
    Dim Tax As DataColumn
    '建立字段对象-总计, 用来指定新建时的默认值
    Dim Amount As DataColumn
    '建立字段对象-数量, 用来指定新建时的默认值
    Dim Quantity As DataColumn
    '建立字段对象-单价, 用来指定新建时的默认值
    Dim UnitPrice As DataColumn




    Private Sub bnFirst_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnFirst.Click
        '首笔记录
        BmOrders.Position = 0
    End Sub

    Private Sub bnPrior_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnPrior.Click
        '上一笔记录
        BmOrders.Position -= 1
    End Sub

    Private Sub bnNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnNext.Click
        '下一笔记录
        BmOrders.Position += 1
    End Sub

    Private Sub bnLast_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnLast.Click
        '末笔记录
        BmOrders.Position = BmOrders.Count - 1
    End Sub

    Private Sub bnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnAdd.Click
        Try
            '新建记录
            BmOrders.EndCurrentEdit()
            BmOrders.AddNew()
        Catch err As System.SystemException
            MessageBox.Show(err.ToString)
        End Try
    End Sub

    Private Sub bnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnDelete.Click
        '删除记录
        If BmOrders.Count > 0 Then
            BmOrders.RemoveAt(BmOrders.Position)
        End If
    End Sub

    Private Sub bnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnCancel.Click
        '取销编辑
        BmOrders.CancelCurrentEdit()
    End Sub

    Private Sub bnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnLoad.Click
        ’加载数据
        FillData()
    End Sub

    Private Sub bnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bnUpdate.Click
        '更新数据
        Dim dsTestChange As DataSet
        '终止目前所有的资料异动    
        '明细先储存再储存主档
        BmOrderDetails.EndCurrentEdit()
        BmOrders.EndCurrentEdit()
        '有删除的数据吗?
        If Not dsTest.HasChanges(DataRowState.Deleted) Then
            Try
                '先更新主档再更新明细档
                daOrders.Update(dsTest, "Orders")
                daOrderDetails.Update(dsTest, "OrderDetails")
                dsTest.AcceptChanges()
            Catch err As System.SystemException
                dsTest.RejectChanges()
                MessageBox.Show(err.ToString)
                Throw
            End Try
        Else
            Try
                '先更新明细档再更新主档
                daOrderDetails.Update(dsTest, "OrderDetails")
                daOrders.Update(dsTest, "Orders")
                dsTest.AcceptChanges()
            Catch err As System.SystemException
                dsTest.RejectChanges()
                MessageBox.Show(err.ToString)
                Throw
            End Try
        End If

    End Sub

    Private Sub fmOrders_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        '先填入资料
        FillData()
        '把dtOrderDetails这个DataTable对象, 指定为dsTest里的OrderDetails
        dtOrderDetails = dsTest.Tables("OrderDetails")
        '把Orders与BmOrders做资料系结
        BmOrders = Me.BindingContext(dsTest, "Orders")
        '把OrderDetailss与BmOrderDetais做资料系结
        BmOrderDetails = Me.BindingContext(dsTest, "Orders.OrdersOrderDetails")
        '一开始, 预设是ColumnChanged事件里的计算程序代码是要执行的
        OrderDetailsHasChange = True
        '把SubTotal这个DataColumn对象, 指定为Orders里的SubTotal
        SubTotal = dsTest.Tables("Orders").Columns("SubTotal")
        SubTotal.DefaultValue = 0
        '把Tax这个DataColumn对象, 指定为Orders里的Tax
        Tax = dsTest.Tables("Orders").Columns("Tax")
        Tax.DefaultValue = 0
        '把Amount这个DataColumn对象, 指定为Orders里的Amounte
        Amount = dsTest.Tables("Orders").Columns("Amount")
        Amount.DefaultValue = 0
        '把Quantity这个DataColumn对象, 指定为OrderDetails里的Quantity
        Quantity = dsTest.Tables("OrderDetails").Columns("Quantity")
        Quantity.DefaultValue = 0
        '把UnitPrice这个DataColumn对象, 指定为OrderDetails里的UnitPrice
        UnitPrice = dsTest.Tables("OrderDetails").Columns("UnitPrice")
        UnitPrice.DefaultValue = 0

    End Sub

    Private Sub FillData()
        '关闭数据表格的条件约束
        dsTest.EnforceConstraints = False
        '填入数据集, 注意顺序
        '填入订单主文件
        daOrders.Fill(dsTest)
        '填入订单明细文件
        daOrderDetails.Fill(dsTest)
        '填入客户档
        daCustomer.Fill(dsTest)
        '打开数据表格的条件约束
        dsTest.EnforceConstraints = True

    End Sub

    Private Sub dtOrderDetails_ColumnChanged(ByVal sender As Object, ByVal e As System.Data.DataColumnChangeEventArgs) Handles dtOrderDetails.ColumnChanged
        '建立DataRow对象-Orders
        Dim drOrders As DataRow
        '建立DataRow对象-OrderDetails
        Dim drOrderDetails As DataRow
        '用来计算总数的变量
        Dim iSubTotal As Integer
        Try
            '如果为False, 就不再进去执行, 避免造成无穷回路
            If OrderDetailsHasChange Then
                '进来先变回False
                OrderDetailsHasChange = False
                '计算明细的金额
                e.Row("DetailAmount") = e.Row("Quantity") * e.Row("UnitPrice")
                '找出目前的Orders所在的记录
                drOrders = dsTest.Tables("Orders").Rows(BmOrders.Position)
                '先归0, 养成习惯, 虽然默认值就是0
                iSubTotal = 0
                '找出每笔明细出来
                For Each drOrderDetails In drOrders.GetChildRows _
                                          ("OrdersOrderDetails")
                    '金额累加
                    iSubTotal = iSubTotal + drOrderDetails("DetailAmount")
                Next
                '变为编辑模式
                drOrders.BeginEdit()
                '明细的总计金额=主档的小计
                drOrders("SubTotal") = iSubTotal
                '计算税额
                drOrders("Tax") = drOrders("SubTotal") * 0.05
                '计算总计 
                drOrders("Amount") = drOrders("SubTotal") + drOrders("Tax")
                '储存, 结束编辑
                drOrders.EndEdit()
            End If
        Finally
            '无论如何, 要把标志变回True
            OrderDetailsHasChange = True
        End Try
    End Sub

#3


是不是学生啊,如果程序要写这么多注释,那就是垃圾!

#4


俺是想把俺的思路写的尽量详细一点,好让各位高手以最快的速度指点错误,正常写程序时是不会写这么多注释的。

#5


晕, 贴了这么多上来, 找了一下, 居然没发现"订单编号不能为空,是否修正"这句话的出处..我都不知道这个出错条件的触发事件是什么你叫我怎么调试??

我一般这样处理:先找到"订单编号不能为空,是否修正"的触发事件,即什么原因导致系统提示这句话, 然后把原因一层一层深入下去.

#6


马客你好!如果你愿意的话,俺把俺的程序及数据库打包发给你,方便的话给俺留个E-mail或QQ号。

#7


可以, 有时间帮你看看吧
mark2win@163.com

#8


谢谢了,俺马上发过去!

#9


写注释是一个好习惯,存在自己思路的地方一般都要写,不然别人维护或者自己以后维护都是一件头痛的事情,这点我想资深人士会深有体会

主细档关联,采用DataGrid这种具有数据绑定功能的控件,只需要将数据源同时绑定到各个控件即可(设置DataSource)

#10


路过...
------------------------------------------------------------------------------------ 
100M.Net空间+50M企业邮局=60元/年
100M.Net空间+国际*域名=100元/年
国际*域名.com.net.cn=50元/年
本站申请域名可绑定免费10M Asp.Net空间
1000M.Net空间 + 100M MsSql数据库 + 1000M企业邮局 + *域名=600元/年
数据库 企业邮局 网站推广 整机租用 美国空间 网站建设 均有售
还有很多优惠套餐提供给各个用户层.
有意者可联系电话:021-64802212 传真:021-64802212 
咨询信箱:info@kingtoo.com 咨询OICQ:68311305,379620139 81778640