none
Adding new details to an existing entity fails RRS feed

  • Question

  • Hi there -

    I have ready various information about maintaining my entities context, but I'm having problems adding a new detail to my (invoice) detail entity.

    Here's what I have:

    A vb.net Windows form application that has various textboxes for my invoice header, followed by a gridview that contains the details of the invoice.  I have a form level variable (context) that holds my entity information.  When I perform a search, I use that context variable to bring back the information and display it in the form.  I can change the header fields and even make changes to existing detail items.  However, when I attempt to add a new detail item from the grid, it appears to have lost it's context when I perform the context.savechanges().

    The goal is to allow a user to add as many details, modify existing ones, and even delete them prior to actually saving them back to the database.

    Is there a best practice for performing normal CRUD logic based upon the scenario described above?  I have posted the code to my test application.  I apologize for the commented out code, but I have tried several differnet variations, just not sure if it makes sense.  Therefore, if I can get a better handle on how to manage my objects context to be used throughout the form, that would be great!

    Thank you

    Bob

        Private context As New ThreeWayMatchEntities    ' Context variable to be used throughout form
        Private addNew As Boolean = False
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            ' Load discount types
            Dim d As ObjectQuery(Of Invoice_Discount_Type) = context.Invoice_Discount_Type.OrderBy("it.Invoice_Discount_Type_ID")
    
            Dim discountType As GridViewComboBoxColumn = RadGridView1.Columns("colDiscountType")
            discountType.DisplayMember = "Invoice_Discount_Type_Description"
            discountType.ValueMember = "Invoice_Discount_Type_ID"
            discountType.DataSource = d.Execute(MergeOption.AppendOnly)
    
            RadGridView1.BestFitColumns()
        End Sub
    
        Private Sub searchInvoice(invoiceID As String)
    
            Dim invID As String = invoiceID
            Dim venID As Integer = 6
    
            ' populate grid and textboxes
            'Using context As New ThreeWayMatchEntities
            ''Dim invoice As ObjectSet(Of Invoice_Header) = context.Invoice_Header
            ''Dim details As ObjectSet(Of Invoice_Detail) = context.Invoice_Detail
    
            ''Dim query = From inv In invoice
            ''            Join det In details
            ''                On inv.Invoice_Header_ID Equals det.Invoice_Header_ID
            ''            Where inv.Invoice_Number = RTrim(invoiceID)
            ''            Select inv, det
    
            ''Dim i = query.FirstOrDefault
    
            Dim i = context.Invoice_Header.FirstOrDefault(Function(x) x.Invoice_Number = TextBox4.Text)
    
            ' ''Dim q = From h In context.Invoice_Header.Include("Invoice_Detail")
            ' ''        Where h.Invoice_Number = invoiceID
            ' ''        Select h
    
            ' ''Dim i = q.FirstOrDefault
    
            Try
                TextBox1.DataBindings.Add(New Binding("Text", i.Invoice_Number, "Invoice_Number"))
                TextBox2.DataBindings.Add(New Binding("Text", i.Title_Count, "Title_Count"))
                TextBox3.DataBindings.Add(New Binding("Text", i.Shipment_Number, "Shipment_Number"))
            Catch ex As Exception
    
            End Try
    
            Try
                TextBox1.Text = i.Invoice_Number
                TextBox2.Text = i.Title_Count
                TextBox3.Text = i.Shipment_Number
    
                RadGridView1.DataSource = i.Invoice_Detail
            Catch ex As Exception
                MsgBox("Invoice Not Found!")
            End Try
            RadGridView1.BestFitColumns()
            'End Using
        End Sub
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Try
                If addNew Then
    
                    Dim h As New Invoice_Header
    
                    h.Vendor_ID = 6
                    h.Invoice_Number = TextBox1.Text
                    h.Invoice_Date = Now
                    h.Payment_Due_Date = Now 'FormatDateTime(Now.AddDays(30), DateFormat.ShortDate)
                    h.Shipment_Number = TextBox3.Text
                    h.Invoice_Discount_Type_Id = 0
                    h.Title_Count = TextBox2.Text
                    h.Image_File_Name = "None"
    
                    h.Created_By = Environment.UserName
                    h.Date_Created = Now
                    h.Last_Updated = Now
                    h.Last_Updated_By = Environment.UserName
    
                    For Each r As GridViewDataRowInfo In RadGridView1.Rows
                        Dim d As New Invoice_Detail
                        d.ISBN_13 = r.Cells("colISBN").Value
                        d.Quantity = r.Cells("colQuantity").Value
                        d.Price = r.Cells("colPrice").Value
                        d.Unit_Net_Price = r.Cells("colUnitNetPrice").Value
                        d.Adjustment = r.Cells("colAdjustments").Value
                        d.Total_Cost = r.Cells("colTotalCost").Value
    
                        d.Date_Created = Now
                        d.Last_Updated = Now
                        d.Last_Updated_By = Environment.UserName
    
                        h.Invoice_Detail.Add(d)
                    Next
    
                    context.Invoice_Header.AddObject(h)
                    context.SaveChanges()
                    addNew = False
                Else
                    context.SaveChanges()
                End If
    
                'context.SaveChanges()
            Catch ex As Exception
    
            End Try
    
        End Sub
    
        Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
            TextBox1.Text = ""
            TextBox2.Text = ""
            TextBox3.Text = ""
    
            RadGridView1.Rows.Clear()
    
            addNew = True
        End Sub
    
        Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
            searchInvoice(TextBox4.Text)
        End Sub
    
        Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
            addNew = False
        End Sub
    
        Private Sub RadGridView1_RowsChanged(sender As System.Object, e As Telerik.WinControls.UI.GridViewCollectionChangedEventArgs) Handles RadGridView1.RowsChanged
    
        End Sub
    
        Private Sub RadGridView1_UserAddedRow(sender As System.Object, e As Telerik.WinControls.UI.GridViewRowEventArgs) Handles RadGridView1.UserAddedRow
            'Dim q = From h In context.Invoice_Header.Include("Invoice_Detail")
            '        Where h.Invoice_Number = TextBox4.Text
            '        Select h
    
            'Dim i = q.FirstOrDefault
            'Using invContext As New ThreeWayMatchEntities
            'Dim i = invContext.Invoice_Header.FirstOrDefault(Function(x) x.Invoice_Number = TextBox4.Text)
            Dim d As New Invoice_Detail
    
            d.ISBN_13 = e.Row.Cells("colISBN").Value
            d.Quantity = e.Row.Cells("colQuantity").Value
            d.Price = e.Row.Cells("colPrice").Value
            d.Unit_Net_Price = e.Row.Cells("colUnitNetPrice").Value
            d.Adjustment = e.Row.Cells("colAdjustments").Value
            d.Total_Cost = e.Row.Cells("colTotalCost").Value
            d.Invoice_Discount_Type_Id = 0
            d.Extended_Price = d.Quantity * d.Unit_Net_Price
            d.Active = True
    
            d.Date_Created = FormatDateTime(Now(), DateFormat.GeneralDate)
            d.Last_Updated = FormatDateTime(Now(), DateFormat.GeneralDate)
            d.Last_Updated_By = Environment.UserName
    
            context.Invoice_Detail.AddObject(d)
            'i.Invoice_Detail.Add(d)
    
            'i.Created_By = Environment.UserName
            'i.Date_Created = Now
            'i.Last_Updated = Now
            'i.Last_Updated_By = Environment.UserName
    
            'invContext.SaveChanges()
            'End Using
        End Sub
    End Class
    

    Thursday, June 7, 2012 8:18 PM

Answers

  • Hi Bob,

    I have checked the code again, the code about EF seems no problem. The code isn't complex, only data binding and data retrieving. Here's an article about EF CRUD in DataGridView, please refer here. This article introduces CRUD with Entity Framework in DataGridView and contains source code. Since the binding control you are using is 3rd party, Telerik Professional Services may help.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, June 13, 2012 6:26 AM
    Moderator

All replies

  • Hi Bob,

    Welcome to MSDN Forum.

    Keeping a context in a short time is a good practice. I would suggest you to create a new instance of ObjectContext everytime you want to do operation with the database. We can instantiate it in a using statement, so that we can ensure the instance will be disposed after CRUD.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Monday, June 11, 2012 5:18 AM
    Moderator
  • Thank you for the reply.

    I have attempted to keep my context as short as possible with using a using/end using block, however I have experienced that when I try and pass my object to either the calling method or another, I receive an exception basically indicating that the handle to the context has been disconnected or lost.

    In contrast to the using/end using block, I have also read that since this is a win form app, that it can be acceptable to keep the context open for a longer period of time.  So currently I have a context that remains in scope while the form is visible and disposed when the form closes.

    With all that being said and based upon your suggestion, if I perform the loading of my head and detail records in a using block and the data is bound to a group of texboxes, dropdowns, etc, and my details are bound to a data grid, when do I perform the CRUD logic on data contained within the datagrid?  My goal is to allow the user to make all additions, deletes and modifications all at once and then click a save button that saves the work.

    I'm a little confused on the data grid...

    Hope that explains a little more to where I can continue to get a little help until I get over this hump.

    Thank you in return!

    Bob

    Monday, June 11, 2012 2:23 PM
  • Hi Bob,

    I have checked the code again, the code about EF seems no problem. The code isn't complex, only data binding and data retrieving. Here's an article about EF CRUD in DataGridView, please refer here. This article introduces CRUD with Entity Framework in DataGridView and contains source code. Since the binding control you are using is 3rd party, Telerik Professional Services may help.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, June 13, 2012 6:26 AM
    Moderator