80bower
80bower

Reputation: 1161

How can I ensure that Entity Framework will create an association in a many-to-many relationship instead of a new record?

I have a problem with Entity Framework.... I don't know it well.

I am working on a seemingly simple task of associating an existing contact to a new order in a system I'm working on. Contacts will always exist prior to being associated to the order.

Simplified database tables...

Order
OrderID
Status
Created

Contact
ContactID
FirstName
LastName

ContactToOrderMap
OrderID
ContactID

I've linked these two tables in the DbContext.

 modelBuilder.Entity<Order>()
                .HasMany<Contact>(a => a.Contacts)
                .WithMany()
                .Map(a =>
                    {
                        a.ToTable("ContactToOrderMap");
                        a.MapLeftKey("OrderID");
                        a.MapRightKey("ContactID");
                    });

I wrote a unit test that simply creates an order, a contact, adds the contact to a list member on the order and attempts to save.

// setup 
var order = new Order() { // initialize required fields };

// add a contact that already exists in the database
var orderContact = new Contact() { ID = 2 }; 
order.Contacts.Add(orderContact);

// call
logic.Save(ref order);

Eventually this order is saved after some unrelated business logic is performed...

// Add to collection
_db.Orders.Add(obj);
// Commit changes
_db.SaveChanges();

>> Here I receive errors related to required database fields on the Contact table. Not what I'm looking for as I really just want to add an association record in the ContactToOrderMap table.

As a next step, I tried to retrieve the existing contacts from the database prior to saving the order. This code's not super clean, but it should explain what I'm attempting.

    if (currentOrder.Contacts != null)
    {
        var matchedContacts = new List<Contact>();

        foreach (var con in currentOrder.Contacts)
        {
            matchedContacts.Add(_contactLogic.Get(con.ID));
        }

        currentOrder.Contacts.Clear();
        foreach (var item in matchedContacts)
        {
            currentOrder.Contacts.Add(item);
        }
    }

This created the association, but created a new Contact (new unique ID) as well.

The goal is to create an association and a new order only, not create a new contact.

Any ideas or pointers to get me going in the right direction?

Please let me know if additional information is required.

Edit: Fixed code - renamed obj to currentOrder.

Upvotes: 2

Views: 832

Answers (1)

Gert Arnold
Gert Arnold

Reputation: 109136

After the line

var orderContact = new Contact() { ID = 2 };

do

_db.Contacts.Attach(orderContact);

Now the contact is part of the context in an Unchanged state, and

order.Contacts.Add(orderContact);

will not change its state to Added anymore.

Upvotes: 3

Related Questions