Add associated entity in code behind

Feb 10, 2011 at 6:02 PM
I'm a bit stuck and the demo project isn't helping.  I have a many to many relationship and I went through all of the steps of adding the M2MRia project and files.  Everything seems to work as fars retreiving the many to many entities and binding in xaml to controls.  However, when I tried to add a new entity on a click event in code behind it doesn't seem to work the way I would expect.  I can get it to add a new record in the link table in the database, but my bound control (Listbox) is not updating.  I've tried several ways and either it errors, creates a db record in the entity table (not the link table), and/or the listbox is not updated correctly.  My many to many relationship is between the RepairOrderDetail and Issue entities.  Here's my code:
 
 <ListBox Name="lstIssues" Grid.Row="7" Grid.Column="4" Grid.RowSpan="2" DisplayMemberPath="Issue.IssueDescription" SelectedValuePath="Issue.IssueID" ItemsSource="{Binding Path=RepairOrderDetail_IssueToIssueSet, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" HorizontalAlignment="Left" Margin="5" Width="150" Height="50" />

  private void addIss_SubmitClicked(object sender, System.EventArgs e)
        {
            EntityCollection<RepairOrderDetail_Issue> issues = lstIssues.ItemsSource as EntityCollection<RepairOrderDetail_Issue>;

            RepairOrderDetail_Issue detailIssue = new RepairOrderDetail_Issue();
            detailIssue.IssueId = newIssue.IssueID;
            detailIssue.RepairOrderDetailId = ((RepairOrderDetail)lstRepairOrderDetail.SelectedItem).RepairOrderDetailID;

            issues.Add(detailIssue);
        }

 

 

Feb 10, 2011 at 8:20 PM

Hi,

Thanks for trying m2m4ria.

You are actually binding the ItemsSource of your control to the link table. This is not really m2m.

With the information you provided, I don't know what the navigation properties of your entities are,
so lets assume your DataContext is bound to a RepairOrderDetail object, which has an Issues property
(this is the m2m assocaition). Now, you xaml may look like:

   <ListBox Name="lstIssues" ItemsSource="{Binding Issues}" />

Your code behind may look like:

   private void addIss_SubmitClicked(object sender, System.EventArgs e)
   {
      RepairOrderDetail rod = (RepairOrderDetail)DataContext;
      rod.Issues.Add(newIssue);
   }

Actually, I'm not sure if adding newIssue to the collection

   lstIssues.ItemsSource as EntityCollection<RepairOrderDetail_Issue>

also works (I've never tried that).
In code fragments above you're really making use of m2m. Under the hood
m2m link table entities are created.

BTW. Assuming you're using server-generated keys, your code behind cannot work.
The problem is that you're setting the primary keys of the newly created link
table entity yourself. In particular the statement:
  
   detailIssue.IssueId = newIssue.IssueID;

is wrong. This is because for newly created entities the value of the primary key
is always zero and can't be used. Instead use the navigation properties of the
object:

   detailIssue.Issue = newIssue;
   detailIssue.RepairOrderDetail = ((RepairOrderDetail)lstRepairOrderDetail.SelectedItem);

Hope this helps.

Feb 10, 2011 at 11:12 PM

Thanks for the reply.  That's some really good info.  I was actually doing it that way (binding to Issues) to begin with.  I figured out what the problem was.  I have a child window where the user selects the Issue that want to add to the RepairOrderDetail and on this page I was instantiating a new domain context to get a full list of Issues to select from.  When I tried to add an Issue from this list to my RepairOrderDetail I was getting an exception saying that the entity was already attached to something else.  And the other thing I tried was just instantiating a new Issue on my main page and adding it to RepairOrderDetail.  This caused a new Issue record to be created in the Issue table in the db...defininately not what I was looking for.  So passing the context from my main page to my child window seems to do the trick, which makes alot of sense. 

Now onto deleting Issues from RepairOrderDetails.  I assume that the code should look pretty similar to the add and it almost works.  The Issue is deleted from the RepairOrderDetail in the db, but for some reason it deletes a different Issue (not the one selected) from the ListBox.  Any thoughts.

<ListBox Name="lstIssues" DisplayMemberPath="IssueDescription" SelectedValuePath="IssueID" ItemsSource="{Binding Path=Issues, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" />
  private void btnDeleteIssue_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (lstIssues.SelectedIndex > -1)
            {
                RepairOrderDetail detail = (RepairOrderDetail)lstRepairOrderDetail.SelectedItem;

                detail.Issues.Remove(((Issue)lstIssues.SelectedItem));
             }
        }
Feb 11, 2011 at 11:07 AM

This is a bug.

Thanks for reporting.

The database is updated correctly, but an incorrect NotifyCollectionChanged event is fired, which has the effect that the wrong element is removed from your listbox.
If you restart your application you will see that the correct elements has actually removed from the database.

I will let you know when I fixed this issue.

Feb 11, 2011 at 1:13 PM

I've just committed a fix for the problem.

After I've finished repairing another issue I'll create a new release.

Until then, you can check-out the latest version at http://m2m4ria.codeplex.com/SourceControl/list/changesets.

Feb 11, 2011 at 11:22 PM

Your fix worked.  Thanks for all your help. 

Feb 11, 2011 at 11:24 PM
No thanks.
Good luck with your project.
________________________________________
From: azuchetto [email removed]
Sent: Saturday, February 12, 2011 12:22 AM
To: Jonge, Merijn de
Subject: Re: Add associated entity in code behind [m2m4ria:245482]

From: azuchetto

Your fix worked. Thanks for all your help.

Read the full discussion online<http://m2m4ria.codeplex.com/discussions/245482#post564941>.

To add a post to this discussion, reply to this email ([email removed]<mailto:[email removed]?subject=[m2m4ria:245482]>)

To start a new discussion for this project, email [email removed]<mailto:[email removed]>

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings<https://m2m4ria.codeplex.com/subscriptions/thread/project/edit> on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


The information contained in this message may be confidential and legally protected under applicable law. The message is intended solely for the addressee(s). If you are not the intended recipient, you are hereby notified that any use, forwarding, dissemination, or reproduction of this message is strictly prohibited and may be unlawful. If you are not the intended recipient, please contact the sender by return e-mail and destroy all copies of the original message.