コード例 #1
0
        public async Task <IActionResult> PutBill([FromRoute] int id, [FromBody] Bill bill)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            if (id != bill.BillId)
            {
                return(BadRequest());
            }

            //https://stackoverflow.com/questions/42735368/updating-related-data-with-entity-framework-core
            var billDBState = billsContext.Bill.Include(b => b.Logs).FirstOrDefault(b => b.BillId == id);

            billsContext.Entry(billDBState).CurrentValues.SetValues(bill);

            var logsDB = billDBState.Logs.ToList();

            foreach (var log in logsDB) //iterate over logs in the DB
            {
                var incomingLog = bill.Logs.SingleOrDefault(l => l.LogEntryId == log.LogEntryId);
                if (incomingLog != null)
                {
                    billsContext.Entry(log).CurrentValues.SetValues(incomingLog);
                }
                else
                {
                    billsContext.Remove(log);
                }
            }

            foreach (var log in bill.Logs)
            {
                if (logsDB.All(i => i.LogEntryId != log.LogEntryId))
                {
                    billDBState.Logs.Add(log);
                }
            }

            //billsContext.Entry(bill).State = EntityState.Modified;
            //result in ALL properties being included in the SQL update (whether they've actually changed or not),
            //EXCEPT for the reference properties for related entities

            //billsContext.Update(bill); //even if log entry ID is the same, log is inserted multiple times.
            //will do the same as above, but will include the reference properties,
            //also include ALL properties on those entities in the update, whether they've changed or not
            //https://stackoverflow.com/questions/51046340/ef-core-2-0-trouble-cascading-inserts-for-related-entities-when-updating-princ

            try
            {
                await billsContext.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!BillExists(id))
                {
                    return(NotFound());
                }
                else
                {
                    throw;
                }
            }

            return(NoContent());
        }