Answered Frustration with LINQ

  • Tuesday, October 09, 2007 7:28 PM
     
     

    6 months ago when I started playing with LINQ I was excited about being able link a WPF listboxes and textboxes to an object representation of a complex relational database.  Even better, I could commit changes to the data with a single SubmitChanges() call.  Today I'm extremely frustrated and feel like I must have missed the boat completely. I'll explain.

     

    My relational data has 3 levels, with multiple tables at 2 levels:

    Customer->Packet

    Customer->Order->OrderDetail

    Customer->Order->Payment

    Customer->Order->Adjustment

    Customer->Order->Note

     

    My original idea was this:

    -Use LINQ to get a Customer

    -Bind directly to the LINQ object.  Use Listboxes or Xceed DataGrids for UI.

    -User can change the data at any level and click Save to SubmitChanges()

     

    Here's my code to get a customer:

    Code Block

    FundCustomer customer;

    var customerset =
         from c in db.FundCustomer
         where c.Custid == custid
         select c;

    if (customerset.Count() > 0)
    {
            customer = customerset.First();
    // Force the data to pull from the DB each time.
            db.Refresh(customer, RefreshMode.OverwriteCurrentValues);
            return customer;
    }

     

     

    The first hurdle was learning that the data in an EntitySet is not static and shouldn't be bound to., but I can call ToBindingList() and bind to that.  This doesn't quite work either because a BindingList doesn't include Update Notification and it cannot be ordered.  So I'm wrapping the BindingList in a BindingListCollectionView and binding DataGrid to the BindingListCollectionView.  This must be done for all 5 child tables.

     

    What started out as a bundled object is now a bunch of disconnected BindingLists.  To make complicate things a bit more, I still have the original objects and the DataContext hanging around.  I like it that I can switch orders (for the same customer) without talking to the SQL Server, but I'm really struggling with a reliable methodology of saving changes.  My code is a mess.

     

    For example, let's say I want to add a new Payment.  Which object does the payment get added to?  I'm adding it to 3 places:

     

    Code Block

    // Create a new adjustment

    FundPayment payment = new FundPayment();

    payment.Refid = this.CurrentOrder.Refid;

    payment.Amount = 0.00m;

    payment.Received = DateTime.Now;

    payment.Method = "";

    // Not sure where to add the payment. Add it everywhere!

    this.CurrentOrder.FundPayment.Add(payment);

    this.Payments.Add(payment);

    this.FundDAL.db.FundPayment.Add(payment);

    // Select the new record and move the focus.

    this.PaymentGrid.CurrentItem = payment;

    this.PaymentGrid.CurrentColumn = this.PaymentGrid.Columns["Amount"];

    this.PaymentGrid.Focus();

     

     

    Adding or removing customers or orders gets even more messy because of the children to deal with...

     

    Any tips on better way to bind to LINQ data?  Can I keep the BindingList tied to the DataContext?  Or do I have to interact with multiple objects when objects are added/removed?

     

    Sorry for the long post.

    Brian

All Replies

  • Tuesday, October 09, 2007 9:47 PM
     
     

    You can use EntitySet.GetNewBindingList() to get a list to bind to. The return type is derived from SortableBindingList which as its name implies is sortable. Though there are still some problems with it (in some cases the content is not synced with the EntitySet), but that can be worked around by manually syncing where necessary.

    As for adding the payment, you only need to estabilish the relation between the order and the payment by either adding the payment to the order's entityset or setting the payment's entityref property to the order (if the order is attached to the DataContext). The DataContext will take care of the rest when you call SubmitChanges by automatically discovering non-attached objects. Or at least it did for beta1, there has been some changes with the attach behavior in beta2, I'm not entirely sure if this scenario is affected or not.

  • Tuesday, October 09, 2007 10:06 PM
     
     

     

    I've been using EntitySet.ToBindingList().  Perhaps this used to be called GetNewBindingList()?  I didn't realize the resulting set is sortable.  I don't believe the resulting BindingList has internal Change Notification though. 

     

    Brian

  • Tuesday, October 09, 2007 10:31 PM
     
     Answered
    EntitySet automatically binds correctly by default now.  No need to call ToBindingList.  GetNewBindingList was added if you need to bind the same EntitySet multiple times to different controls and want them to function independently from each other.

     

  • Tuesday, October 09, 2007 11:11 PM
     
     

    Matt

     

    Could you possibly elaborate on what are the planned changes for beta2 to RTM regarding this particular problem when directly binding the EntitySet to a BindingSource?

     

    Thanks in advance.