none
EF 6.x, Winform Data Binding, howto make work and use filtering. RRS feed

  • Question

  • When I built the solution under VS2010 with .net 4.0 and EF 4.0 all ran fine.  I converted to VS2015 and could not add tables from the DB via the designers DB update as I was not running EF 6 or EF 5. After several hours I implemented EF 6.x and .net 4.5 changes to get the code running again under VS2015. I have 99% of things working just fine except 1 form which data binds the DB into a single Master/Detail form. The form is in the Main Desktop application that allows for maintenance. I simply cannot get data into the form from any "linked" table (customer or Detail). I have explored the EF6Winforms from http://www.codeproject.com/Articles/221931/Entity-Framework-in-WinForms but I cannot access the navigation for the Details or the Customers.  The header and customer data is presented in label fields bound to the Binding source and the Detail is shown in a DataGridView.

    So can anyone point me in the right direction to allow a display of Master/Detail in a winform and allow filtering on user entered data?  Below is the detail of the form and application(s).

    Overall project is as follows.

    There is an Order Header Table with an SQL constraint to the Details file and customer file.  1 Customer per order, 1 order per detail, unknown # of details. All data and constraints are defined in SQL server 2012. Again this all worked well under ef4.0 object context, it's just that I could no longer update the EDMX from the DB.

    Task is to import/export data from multiple sources such as ODBC, SOAP, JSon interfaces and store into a common Order Header/Detail Database. Multiple orders to the same customer are merged together as single processing order. This DB must be managed by certain end users, other users require only Access to process the orders. This dictates that there are two different Desktop Applications using the EDMX. In addition to the desktop apps there is a Windows service that will also auto Process the Import and Exports on an hourly basis.

    This is why I used EF over a Dataset, shared Typed Datasets took a lot of maintenance in multiple apps within a single solution set of applications and linking the Dataset in multiple solutions caused headaches with "edited in another app" and other such annoying factors. 

    I built the EDMX in a class library. The Class Library also defines all of the Import and Export processes. So this is not a true n-Tier application. The class in "used" by all Desktop Apps and the windows Service app.

    I've run into several issues with this form the first is getting the data bound to the form.  I use LinQ to filter the data, a leftover from EF4.0 and then assigned the Result set to the BindingDatasource, this no longer works in any way as is does not implement ToList(). User can set Filter properties and the form auto responds to the Data entry within the filter fields by calling the SetForm sub from events.

    It is important that the user can change not only header info but the linked address and details, no add, no delete.  When the user moves from header record to the next or closes the form existing updates must be applied there is no undo. I handle data entry errors by controlling what is edited and validation processes.  I know, bad design, but an end user "must be this way."

    Here is the code that ran under EF4.0:

    Public Class frmReviewOrders

      Private brunning As Boolean = False

      Private ctxt As clsInterfaces.OrderEntities

     Private Sub frmReviewOrders_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

      Dim dt As Date = Date.Today.AddDays(-1)
      If Date.Today.DayOfWeek = DayOfWeek.Monday Then
       dt = Date.Today.AddDays(-3)
      End If
      dtpAftrDate.Value = dt 'DateTimeSelection tool.
      ctxt = New clsInterfaces.OrderEntities(strEFCnnStr)
      brunning = True

    SetForm()

     End Sub

     Private Sub SetForm()

      Dim query
      Dim isfid As Integer = 0
      Dim seldate As Date = dtpAftrDate.Value
      If Not brunning Then
       Exit Sub
      End If

      If Not cbBusUnit.Text.ToLower = "all" Then 'ComboBox with which business unit the order is from
       isfid = (From s In ctxt.ShipFroms Where s.Channel = cbBusUnit.Text Select s.SFid).FirstOrDefault
      End If

      If Me.cbSelStat.Text = "Any" Then 'Filter by Order Status?
       If isfid <> 0 Then
        query = ctxt.ShipHdrs.Where(Function(sh) sh.OrdNo.StartsWith(txtOrderNo.Text) And sh.SFID = isfid And sh.ImpDte >= seldate).OrderBy(Function(sh1) sh1.OrdNo) 'Limit to what op selects is Editbox
       Else
        query = ctxt.ShipHdrs.Where(Function(sh) sh.OrdNo.StartsWith(txtOrderNo.Text) And sh.ImpDte >= seldate).OrderBy(Function(sh1) sh1.OrdNo)
       End If
      Else
       If isfid <> 0 Then 'Limit to Specific Business unit?
        query = ctxt.ShipHdrs.Where(Function(sh) sh.ShipStatus = Me.cbSelStat.Text And sh.SFID = isfid And sh.ImpDte >= seldate).OrderBy(Function(sh1) sh1.OrdNo)
       Else
        query = ctxt.ShipHdrs.Where(Function(sh) sh.ShipStatus = Me.cbSelStat.Text And sh.ImpDte >= seldate).OrderBy(Function(sh1) sh1.OrdNo)
       End If
      End If

      ShipHdrBindingSource.DataSource = query

     Application.DoEvents()

     End Sub

    Monday, April 25, 2016 8:43 PM

All replies

  • Hi Mudoch2505,

    Please try modify this line

    ShipHdrBindingSource.DataSource = query
    to

    ShipHdrBindingSource.DataSource = query.ToList()

    if it still has the issue, could you please provide a bit more information (such as detailed error message).

    Best regards,

    Cole Wu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, April 26, 2016 8:57 AM
    Moderator
  • Tried that before, Added the tolist() which by the way is not flagged as an error in the IDE but when executed:

    System.MissingMemberException was unhandled
      HResult=-2146233070
      Message=Public member 'tolist' on type 'DbQuery(Of ShipHdr)' not found.
      Source=Microsoft.VisualBasic
      StackTrace:
           at Microsoft.VisualBasic.CompilerServices.Symbols.Container.GetMembers(String& MemberName, Boolean ReportErrors)
           at Microsoft.VisualBasic.CompilerServices.NewLateBinding.ObjectLateGet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack)
           at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack)
           at NGPDataMgr.frmReviewOrders.SetForm() in E:\2010 Projects\VisionaryBrands\NGPDataMgr\frmReviewOrders.vb:line 85
           at NGPDataMgr.frmReviewOrders.frmReviewOrders_Load(Object sender, EventArgs e) in E:\2010 Projects\VisionaryBrands\NGPDataMgr\frmReviewOrders.vb:line 36
           at System.Windows.Forms.Form.OnLoad(EventArgs e)
           at System.Windows.Forms.Form.OnCreateControl()
           at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
           at System.Windows.Forms.Control.CreateControl()
           at System.Windows.Forms.Control.WmShowWindow(Message& m)
           at System.Windows.Forms.Control.WndProc(Message& m)
           at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
           at System.Windows.Forms.Form.WmShowWindow(Message& m)
           at System.Windows.Forms.Form.WndProc(Message& m)
           at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
           at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
           at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
           at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow)
           at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
           at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
           at System.Windows.Forms.Control.Show()
           at NGPDataMgr.frmMain.ReviewOrdersToolStripMenuItem_Click(Object sender, EventArgs e) in E:\2010 Projects\VisionaryBrands\NGPDataMgr\frmMain.vb:line 141
           at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
           at System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
           at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
           at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
           at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
           at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
           at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
           at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
           at System.Windows.Forms.Control.WndProc(Message& m)
           at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
           at System.Windows.Forms.ToolStrip.WndProc(Message& m)
           at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
           at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
           at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
           at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
           at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
           at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
           at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
           at NGPDataMgr.My.MyApplication.Main(String[] Args) in :line 81
           at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ThreadHelper.ThreadStart()
      InnerException:

    Tuesday, April 26, 2016 5:29 PM
  • Hi Mudoch2505,

    From your code snippet, I create a similar demo and reproduce your issue on my side, please could define the variable named query as IQueryable(Of ShipHdr), like below:

    Dim query As IQueryable(Of ShipHdr)

    Then you could use the method name ToList

    ShipHdrBindingSource.DataSource = query.ToList()

    In addition, you could also add the method named ToList() in your linq to entities. as below:

    If Me.cbSelStat.Text = "Any" Then 'Filter by Order Status?
        If isfid <> 0 Then
         query = ctxt.ShipHdrs.Where(Function(sh) sh.OrdNo.StartsWith(txtOrderNo.Text) And sh.SFID = isfid And sh.ImpDte >= seldate).OrderBy(Function(sh1) sh1.OrdNo).ToList() 'Limit to what op selects is Editbox
        Else
         query = ctxt.ShipHdrs.Where(Function(sh) sh.OrdNo.StartsWith(txtOrderNo.Text) And sh.ImpDte >= seldate).OrderBy(Function(sh1) sh1.OrdNo).ToList() 
        End If
       Else
        If isfid <> 0 Then 'Limit to Specific Business unit?
         query = ctxt.ShipHdrs.Where(Function(sh) sh.ShipStatus = Me.cbSelStat.Text And sh.SFID = isfid And sh.ImpDte >= seldate).OrderBy(Function(sh1) sh1.OrdNo)).ToList() 
        Else
         query = ctxt.ShipHdrs.Where(Function(sh) sh.ShipStatus = Me.cbSelStat.Text And sh.ImpDte >= seldate).OrderBy(Function(sh1) sh1.OrdNo)).ToList() 
        End If
       End If
    
      ShipHdrBindingSource.DataSource = query

    Best regards,

    Cole Wu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Wednesday, April 27, 2016 1:43 AM
    Moderator
  • Well this solved the main form issue but now created an issue with the DatgaGridView.  For some reason the error is thrown to a dialog box and not captured by a Try..catch. It complains about data reflection errors on every record before I can see anything on the screen.

    When I break on the set bindingsource for the header I did a watch on the query results. Found that the results did indeed have a shipdets data. So now the question is shifted. The DataGridview is bound to the ShipDetsBindingSource control, that control is bound to the  ShipHdrBindingSource, datamember ShipDets. So I'm certain that the ToList() has something to do with the error.

    Given the Code from the original post and your (successful Iqueryable(of) and ToList()) changes how do I link the DataGridview to show the detail rows in the query result based on the selected Header row?

    Wednesday, April 27, 2016 3:05 PM