views:

171

answers:

1

I have 3 tables: Companies, Subcontracts, and CompanyToSubcontract

The CompanyToSubcontract table is the guid of the Company and guid of the Subcontract. I have a MultiSelectList on the Subcontract Edit and Create views where the user can select multiple companies. I finally got it working where it displays the correct companies as selected in the Subcontract Edit view. I'm not having an issue with saving the data.

In the create view, the subcontract doesn't have a guid until it's written to the Sql database, so how can I get the guid to save to the CompanyToSubcontract table?

Also, in the edit view, I'm doing something wrong. It doesn't save.the company selections. I also need to delete records for companies which are unselected. What is the best way to go about doing that?

I followed the NerdDinner tutorial to get my basic structure and now I'm trying to update to fulfill my needs.

Anyone who can point me in the right direction?

In SubcontractRepository:

public void Save()
    {
        db.SubmitChanges();
    }

In Controller:

 [AcceptVerbs(HttpVerbs.Post), Authorize]
    public ActionResult Edit(string id, FormCollection formValues)
    {
        // Retrieve existing subcontract
        subcontract subcontract = subcontractRepository.GetSubcontract(id);

        if (subcontract == null)
            return View("NotFound");
        else
        {
            try
            {
                UpdateModel(subcontract);

                IEnumerable<Guid> selectedCompanies = Request.Form["Companies"].Split(new Char[] { ',' }).Select(idStr => new Guid(idStr));

                foreach (var item in selectedCompanies)
                {
                    CompanyToSubcontract cs = new CompanyToSubcontract();
                    cs.subcontract_id = subcontract.subcontract_id;
                    cs.company_id = item;
                    subcontractRepository.Save();
                }


                subcontract.lastupdate_date = DateTime.Now;
                subcontract.lastupdatedby_user = User.Identity.Name;

                //Persist changes back to database
                subcontractRepository.Save();

                //Perform HTTP redirect to details page for the saved subcontract
                return RedirectToAction("Details", new { id = subcontract.subcontract_no });
            }
            catch
            {
                ModelState.AddRuleViolations(subcontract.GetRuleViolations());

                return View(new SubcontractFormViewModel(subcontract));
            }

        }
    }
+1  A: 

In the selectedCompanies foreach loop, change:

cs.subcontract_id = subcontract.subcontract_id;

to:

cs.subcontract = subcontract;

The reason why this works is explained in detail in my response to this question. In addition, LINQ-to-SQL also manages the assignment of primary keys and their propagation to foreign keys automatically. When you call db.SubmitChanges(), it recognizes that if the subcontract object doesn't have a foreign key assigned, it treats it as an INSERT change. Also, since the subcontract object is being associated with a CompanyToSubcontract object, it knows to update the foreign key field in the association entity with the primary key value it just assigned to the Subcontract entity.

Neil T.
When I change it from subcontract_id to subcontract it tells me that Models.CompantyToSubcontract doesn't contain a definition for subcontract.
RememberME
Just realized that I also need to delete records for companies which are unselected. What is the best way to go about doing that?
RememberME
Do you have a foreign key relationship between the CompanyToSubcontract and the Subcontract tables in the database?
Neil T.
I'm assuming that the companies you are deleting have no CompanyToSubcontract records. That being said, delete the Company entities first using DeleteOnSubmit(), then call SubmitChanges().
Neil T.
No, I do not need to actually delete the company. When editing the subcontract, if Company1 and Company2 were previously selected and saved in CompanyToSubcontract, they are unselected and Company3 and Company4 are selected, I not only need to write records for Company3 and Company4 to CompanyToSubcontract, but I also need to delete the records for Company1 and Company2 in the link table.
RememberME
The Company, Subcontract, and CompanyToSubcontract tables all need to be reflected in the .dbml for the best results.
Neil T.
Use CompanyToSubcontract.InsertOnSubmit() for the entities you wish to add, and CompanyToSubcontract.DeleteOnSubmit() for those entities you wish to remove. When you are done, call SubmitChanges() on the DataContext, and it should give you the result you're looking for.
Neil T.
When I loop through the selected items, how will I know if the item is new (needs to be added)? How will I know if another item was deselected and needs to be removed? Thanks for all of your help. I'm new to web apps, MVC, and LinqToSql and I'm really hitting a wall here.
RememberME
You will probably need to have a separate collection of the items that already exist. With that, all you'll have to do is something like: if (originalCollection.Contains(companyToCheck)) DeleteOnSubmit(companyToCheck); else InsertOnSubmit(companyToCheck);. It's hard to really guide you to a solution without seeing what you've got. Hopefully, I'm not totally confusing you. I've been where you are, and it's not fun while you're there, but it's really nice once you get to the other side.
Neil T.
Thank you so much. My linking problem was due to the link table not having a primary key. I'm having a much easier time now that I've figured that out.
RememberME