简体   繁体   中英

Saving a form in POST edit doesn't work

I have a controller method in which I'm trying to save a form that was edited in the view.

[HttpPost]
public ActionResult ModifyContract(ModContract mod)
{
    // submit modified contract
    if (ModelState.IsValid)
    {
        OutlookMediaEntities1 db = new OutlookMediaEntities1();

        db.ObjectStateManager.ChangeObjectState(mod, EntityState.Modified);

        // save changes
        db.SaveChanges();

        return RedirectToAction("ContractDetails", "Contract", new { id = (int) ViewData["contractid"] });
    }
    else
    {
        ModelState.AddModelError("", "Missing necessary information");
        return View();
    }
}

I'm getting a InvalidOperationException on the db.ObjectStateManager... line. I saw something that said it might be because I didn't assign a primary key and noticed my ModAds class (below) didn't include a primary key. Added it but I get the same error. I tried doing a db.Attach(mod) as suggested by an answerer in my earlier question, but I get a compiler error. Attach takes as a parameter a "IEntityWithKey". So apparently my entity doesn't have a key, so I'm thinking something must be wrong with how I'm declaring the model stuff.


    public class ModContract
    {
        public int contract_id; // primary key?
        public string contract_name { get; set; }
        public List<ModAds> ads;

        public string print_product_id { get; set; }
        public string print_ad_option_id { get; set; }
    }

    public class ModAds
    {
        public int contr_ad_id; // primary key?
        public string name;
        public string product_name;
        public string adv_product;
        public List<string> editions;
        public double freq_disc;
        public double other_dis_dol;
        public double? other_dis_per;
        public string non_cash_note;
        public double non_cash_cons;
    }

Is there a way to specify what the primary key is? My model is kind of weird because I have a list of ModAds in ModContract as you can see. Not sure if that could be a problem. Also I tried adding getters and setters to all of the field to see if that was the problem but I got the same errors.

I also tried to save with db.Entry(model).State = EntityState.Modified; but it didn't work because I'm using EF 4.0.

Any help is greatly appreciated!

EDIT

I think I know what's wrong, the model was made from a bunch of different database tables, ie there's no table ModContract. I'm pretty sure I have to somehow disperse the model stuff into the appropriate tables and columns..

EDIT 2

Pastebin of OutlookMediaEntities1: http://pastebin.com/YyrhjGDA

EDIT 3

Here's the GET ModifyContract method that shows how I'm querying the database to make the model.

    public ActionResult ModifyContract(int id)
    {
        ViewData["contractid"] = id; // save id

        // get data from db
        OutlookMediaEntities1 db = new OutlookMediaEntities1();
        var cont = from printContractAd in db.print_contract_ads
                   from printContracts in db.print_contracts
                   where printContracts.contract_id == id
                   select new { printContracts.contract_id, printContracts.note }; // name

        // select the ads for this contract
        var ads = from printContractAd in db.print_contract_ads
                  from printAdOption in db.print_ad_option
                  from printContract in db.print_contracts
                  from printProduct in db.print_products
                  from contractAdCount in db.Contract_ad_edition_count
                    where printContractAd.print_ad_option_id == printAdOption.print_ad_option_id &&
                          printContract.contract_id == printContractAd.contract_id &&
                          printProduct.print_product_id == printAdOption.print_product_id &&
                          contractAdCount.contract_ad_id == printContractAd.contract_ad_id &&
                          printContract.contract_id == id
                  select new
                  {
                      printContractAd,
                      printAdOption,
                      printProduct,
                      printContract.IsSigned,
                      contractAdCount.CountFreq
                  };

        ModContract con = new ModContract();
        foreach (var c in cont) // only one
        {
            con.contract_id = c.contract_id;
            con.contract_name = c.note;

            break; // only one
        }

        List<ModAds> cads = new List<ModAds>();
        foreach (var ad in ads)
        {
            ModAds mad = new ModAds();
            mad.contr_ad_id = ad.printContractAd.contract_ad_id;
            mad.product_name = ad.printProduct.product_name;
            mad.adv_product = ad.printAdOption.name;
            mad.name = ad.printContractAd.note;
            mad.freq_disc = ad.printContractAd.frequency_discount;
            mad.other_dis_dol = ad.printContractAd.other_discount;
            mad.other_dis_per = ad.printContractAd.other_discount_percent;
            mad.non_cash_note = ad.printContractAd.non_cash_note;
            mad.non_cash_cons = ad.printContractAd.non_cash_discount; // consideration?

            // get editions
            var eds = from contractEditions in db.print_contract_editions
                      where contractEditions.contract_ad_id == ad.printContractAd.contract_ad_id
                      select new
                          {
                              contractEditions
                          };
            mad.editions = new List<string>();
            foreach (var ed in eds)
            {
                mad.editions.Add("Volume " + ed.contractEditions.vol.ToString() + " Issue " + ed.contractEditions.issue.ToString());
            }

            cads.Add(mad);
        }

        con.ads = cads;

        // bind dropdownlist ad options
        var printproductList = from printProduct in db.print_products
                               select printProduct;
        List<SelectListItem> products_list = new List<SelectListItem>();
        List<print_products> products = printproductList.ToList();
        foreach (print_products product in products)
        {
            SelectListItem temp_item = new SelectListItem();
            temp_item.Text = product.product_name;
            temp_item.Value = product.print_product_id.ToString();
            products_list.Add(temp_item);
        }
        ViewData["products_list"] = new SelectList((IEnumerable<SelectListItem>)products_list.ToList(), "Value", "Text");

        // return view with form to modify
        return View(con);
    }

EDIT 4

Here's the view too if it helps (I couldn't get it format right on here): http://pastebin.com/SZvzJ9FB

for updating an entity , the entity must be attached to Data Context .for doing this getting the entity from data context with Single method would be enough. try changing your code like this :

[HttpPost]
public ActionResult ModifyContract(ModContract mod)
{
    // submit modified contract
    if (ModelState.IsValid)
    {
        OutlookMediaEntities1 db = new OutlookMediaEntities1();

        var updatedMod = db.ModContract.Single(m=>m.contract_id == mod.contract_id);
        TryUpdateModel<ModContract>(updatedMod);
        // save changes
        db.SaveChanges();

        return RedirectToAction("ContractDetails", "Contract", new { id = (int) ViewData["contractid"] });
    }
    else
    {
        ModelState.AddModelError("", "Missing necessary information");
        return View();
    }
}

您可以在ModAds类的主键上方添加[Key]属性。

You could tell EF that contract_id is the key:

public class ModContract
{
    [Key]
    public int contract_id;
}

and make sure that the database column that the property maps to is a PK . It may matter though that it's an IDENTITY or not based on how you use it.

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