简体   繁体   中英

Add object to table containing List of other objects using Entity Framework

I'm adding an object to a table in the database, adding a contact of MarketingContact type. These are my model classes:

public class MarketingContact
    {
        public MarketingContact()
        {
            this.ContactTags = new List<ContactTag>();
        }

        public int id { get; set; }
       //..some other properties not complex properties...
        public virtual ICollection<ContactTag> ContactTags { get; set; }
    }

This is the ContactTag model:

 public class ContactTag
    {
        public ContactTag()
        {
            this.MarketingContacts = new List<MarketingContact>();
        }

        public int TagId { get; set; }
       //some other no complex properties...
        public virtual ICollection<MarketingContact> MarketingContacts { get; set; }
    }

And this is my AddContact() method in my controller:

 [HttpPost]
        public ActionResult AddContact(MarketingVM marketingContactVM)
        {            
            List<ContactTag> contactTags = new List<ContactTag>();
            for (int i = 0; i < marketingContactVM.MarketingContacts.Count; i++)
            {
                if (marketingContactVM.MarketingContacts[i].IsSelected==true)
                {
                    contactTags.Add(new ContactTag { Name = marketingContactVM.MarketingContacts[i].Name, TagId = marketingContactVM.MarketingContacts[i].TagId,
                    InfusionSoftId = marketingContactVM.MarketingContacts[i].InfusionSoftId});
                }
            }
            MarketingContact marketingContact = AutoMapper.Mapper.Map<MarketingContact>(marketingContactVM);
            marketingContact.ContactTags = contactTags;                  
             context.MarketingContacts.Add(marketingContact);
             context.SaveChanges();          
            return Json(new { result = "success"}, JsonRequestBehavior.AllowGet);
        }    

Note that in my controller action I'm making use of a ViewModel( MarketingVM type ). At the time that I save into the database the MarketingContact object is saved in the MarketingContacts table, but in the ContactTags table new rows are created depending on what the ContactTags ICollection that belong to marketingContact contains, and I'm just selecting from ContactTags , the rows are already there, I don't need more rows with same values added in ContactTags table, why is this happening? At the moment I save the object into the database the marketingContact object contains a ContactTags collection with fields existing in the ContactTags table, including the correct TagId values, but instead of just relate them to that row in the MarketingContacs table it create new rows in the ContactTags table with the same values except for the TagId (it generates a new value) therefore the values are duplicated everytime in the ContactTags table and I don't need that. What would I need to change?

The problem is that when you call

context.MarketingContacts.Add(marketingContact);

EF iterates the ContactTags collection and marks each object which is not currently tracked by (loaded in, attached to) context as new.

Since you know they are existing entities, you have to tell that to EF. One way to do that is to attach them to the context (which will mark them as Unchanged ) before adding the main entity.

For instance, you can change

contactTags.Add(new ContactTag { Name = marketingContactVM.MarketingContacts[i].Name, TagId = marketingContactVM.MarketingContacts[i].TagId,
InfusionSoftId = marketingContactVM.MarketingContacts[i].InfusionSoftId});

to

// Note: setting just TagId would be enough
var contactTag = new ContactTag { Name = marketingContactVM.MarketingContacts[i].Name, TagId = marketingContactVM.MarketingContacts[i].TagId,
InfusionSoftId = marketingContactVM.MarketingContacts[i].InfusionSoftId};
contactTags.Add(contactTag);
// the next line will give you the desired behavior
context.ContactTags.Attach(contactTag);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM