Получение следующей ошибки при сохранении дочерних записей с использованием Entity Framework в .net Core - PullRequest
0 голосов
/ 15 мая 2018

Сообщение об ошибке:

Операция базы данных, как ожидается, затронет 1 строку (и), но фактически затронула 0 строк. Данные могут быть изменены или удалены, так как объекты были загружены

Сценарий : У меня есть приложение-запрос на обслуживание, которое я конвертирую в ядро ​​.net.

В приложении много таблиц. Основной родительской таблицей являются запросы на обслуживание. Существует ряд дочерних таблиц, которые успешно обновляются при внесении изменений. Однако это не таблица сведений о файле, предназначенная для загрузки вложений.

Стандартные строительные леса использовались для генерации кода для контроллера. Таким образом, он имеет необходимый индекс, удаляет, создает и редактирует код IActionResult в контроллере. Весь этот код и эти операции работают отлично.

В дополнение к этому у меня есть отдельный IActionResult для загрузки файлов. Вот код:

public IActionResult UpLoadFiles()
{
    return View();
}

[HttpPost]
public async Task<IActionResult> UpLoadFiles(ICollection<IFormFile> files, ServiceRequests serviceRequests, int id)
{
    // Attached File Processing
    string path = null;

    var uploads = Path.Combine(_environment.WebRootPath, "uploads");

    foreach (var file in files)
        try
        {
            if (file == null || file.Length == 0)
                return Content("file not selected");
            else
            {
                using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
                {
                    await file.CopyToAsync(fileStream);
                }

                var fileName = Path.GetFileName(file.FileName);
                path = uploads + "\\" + fileName;

                serviceRequests.FileDetails.Add(new FileDetails()
                    {
                        FileName = fileName,
                        Extension = Path.GetExtension(fileName),
                        Id = Guid.NewGuid(),
                        ServiceRequestId = id
                    });

                // _context.Update(serviceRequests);
                _context.Add(serviceRequests.FileDetails);
                await _context.SaveChangesAsync();

                ViewBag.Message = " Files Uploaded";

                return RedirectToAction("Index");
            }
        }
        catch
        {
            ViewBag.Message = "Upload Failed";
        }

        return View();
}

Приведенный выше код вызывается со страницы редактирования для запроса на обслуживание как ссылка asp-action. Int id - это номер запроса на обслуживание, переданный со страницы просмотра.

Почти весь код работает так, как я его отлаживаю. Вложенный файл сохраняется в папке загрузки, и имя файла, расширение, идентификатор и запрос на обслуживание заполняются правильно, чтобы создать дочернюю запись.

Однако, когда я получаю ждать _context.SaveChangesAsync (); Я получаю сообщение об ошибке в начале потока. Когда я пропускаю строки _context.add или _context.update - ошибки не возникает, но ничего не фиксируется в таблице на сервере SQL.

Возможно, это просто что-то маленькое, но я не могу обойти запись, правильно зафиксированную в таблице filedetails. Эта дочерняя запись является добровольной - не все запросы должны иметь прикрепленный файл.

Полагаю, я мог бы иметь отдельный вид и контроллер для файловых деталей и ввести туда запрос на обслуживание. Но это отрицает цель простого ввода дополнительных дочерних записей в режиме редактирования родительской записи / объекта

Есть мысли о том, чего мне не хватает при использовании платформы сущностей в ядре .net?

Вот остаток кода контроллера до общего кода, ранее предоставленного:

using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using MimeKit;
using ServeMeHRCore21.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System.IO;

namespace ServeMeHRCore21.Controllers
{
    public class ServiceRequestsController : Controller
    {
        private readonly ServeMeHRCoreContext _context;
        private IHostingEnvironment _environment;

        public ServiceRequestsController(ServeMeHRCoreContext context, IHostingEnvironment environment)
        {
            _context = context;
            _environment = environment;
        }


        // GET: ServiceRequests
        public async Task<IActionResult> Index(string StatusType, string searchString)
        {
            IEnumerable<SelectListItem> statusitems = _context.StatusTypes.Select(c => new SelectListItem
            {
                Selected = c.Id == 1,
                Value = c.StatusTypeDescription,
                Text = c.StatusTypeDescription
            });
            ViewBag.StatusType = statusitems;

            ViewBag.CurrentFilter = searchString;
            if (StatusType == null)
                StatusType = "Open";

            var serveMeHRCoreContext = _context.ServiceRequests.Include(s => s.MemberNavigation).Include(s => s.PriorityNavigation).Include(s => s.RequestTypeNavigation).Include(s => s.RequestTypeStepNavigation).Include(s => s.StatusNavigation).Include(s => s.TeamNavigation).Where(s => s.StatusNavigation.StatusTypeNavigation.StatusTypeDescription == StatusType);

            if (!String.IsNullOrEmpty(searchString))
            {
                serveMeHRCoreContext = serveMeHRCoreContext.Where(s => s.RequestHeading.Contains(searchString) || s.RequestDescription.Contains(searchString));
            }

            return View(await serveMeHRCoreContext.ToListAsync());
        }

        // GET: ServiceRequests/Details/5
        public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var serviceRequests = await _context.ServiceRequests
                .Include(s => s.MemberNavigation)
                .Include(s => s.PriorityNavigation)
                .Include(s => s.RequestTypeNavigation)
                .Include(s => s.RequestTypeStepNavigation)
                .Include(s => s.StatusNavigation)
                .Include(s => s.TeamNavigation)
                .SingleOrDefaultAsync(m => m.Id == id);
            if (serviceRequests == null)
            {
                return NotFound();
            }

            return View(serviceRequests);
        }

        // GET: ServiceRequests/Create
        public IActionResult Create()
        {
            ViewData["Member"] = new SelectList(_context.Members, "Id", "MemberEmail");
            ViewData["Priority"] = new SelectList(_context.Priorities, "Id", "PriorityDescription");
            ViewData["RequestType"] = new SelectList(_context.RequestTypes, "Id", "RequestTypeDescription");
            ViewData["RequestTypeStep"] = new SelectList(_context.RequestTypeSteps, "Id", "StepDescription");
            ViewData["Status"] = new SelectList(_context.StatusSets, "Id", "StatusDescription");
            ViewData["Team"] = new SelectList(_context.Teams, "Id", "TeamDescription");

            string homePhone;
            string givenName;
            string surname;
            string email;

            var model = new ServiceRequests();
            model.RequestorId = User.Identity.Name;

            ViewBag.FileUp = _context.ApplicConfs.Select(s => s.FileSystemUpload).FirstOrDefault();

            Boolean ADconf = _context.ApplicConfs.Select(s => s.Adactive).FirstOrDefault();

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) & (ADconf))
            {
                GetADinfo(out givenName, out surname, out homePhone, out email);

                model.RequestorFirstName = givenName;
                model.RequestorLastName = surname;
                model.RequestorEmail = email;
                model.RequestorPhone = homePhone;
                model.RequestType = 1;
            }

            return View(model);
        }

        // POST: ServiceRequests/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("Id,RequestHeading,RequestDescription,RequestorId,RequestorFirstName,RequestorLastName,RequestorPhone,RequestorEmail,DateTimeSubmitted,DateTimeStarted,DateTimeCompleted,Priority,RequestType,RequestTypeStep,Member,Status,Team")] ServiceRequests serviceRequests, ICollection<IFormFile> files)
        {
            if (ModelState.IsValid)
            {
                string homePhone;
                string givenName;
                string surname;
                string email;

                Boolean ADconf = _context.ApplicConfs.Select(s => s.Adactive).FirstOrDefault();

                if (ADconf)
                {
                    GetADinfo(out givenName, out surname, out homePhone, out email);
                    ViewBag.RequestorFirstName = givenName;
                    ViewBag.RequestorLastName = surname;
                    ViewBag.RequestorPhone = homePhone;
                    ViewBag.RequestorEmail = email;
                }




                _context.ServiceRequests.Include(i => i.IndividualAssignmentHistories).Include(i => i.TeamAssignmentHistories).Include(i => i.FileDetails);
                _context.ServiceRequests.Add(serviceRequests);
                serviceRequests.DateTimeSubmitted = DateTime.Now;
                serviceRequests.Status = 1;
                serviceRequests.RequestorId = User.Identity.Name;

                //================================================================================
                //Create a history record for team assignment

                serviceRequests.TeamAssignmentHistories.Add(new TeamAssignmentHistories()
                {
                    DateAssigned = DateTime.Now,
                    AssignedBy = User.Identity.Name,
                    ServiceRequest = serviceRequests.Id,
                    Team = serviceRequests.Team
                });
                //================================================================================

                //================================================================================
                //Create history record for individual assignment
                serviceRequests.IndividualAssignmentHistories.Add(new IndividualAssignmentHistories()
                {
                    DateAssigned = DateTime.Now,
                    AssignedBy = User.Identity.Name,
                    //AssignedTo = "A3HR.Lyndon",
                    AssignedTo = serviceRequests.Member.Value,
                    ServiceRequest = serviceRequests.Id
                });
                //================================================================================

                //Create request step history record===============================================
                serviceRequests.StepHistories.Add(new StepHistories()
                {
                    LastUpdated = DateTime.Now,
                    RequestTypeStep = serviceRequests.RequestTypeStep.Value,
                    ServiceRequest = serviceRequests.Id
                });

                //=================================================================================




                _context.Add(serviceRequests);
                await _context.SaveChangesAsync();

                //Check and see if in application configuration email confirmation is set on========
                Boolean emailconf = _context.ApplicConfs.Select(s => s.EmailConfirmation).FirstOrDefault();

                if (emailconf)
                {
                    SendStatusConfirmation(1, serviceRequests.RequestorEmail);
                }


                return RedirectToAction(nameof(Index));
            }
            ViewData["Member"] = new SelectList(_context.Members, "Id", "MemberEmail", serviceRequests.Member);
            ViewData["Priority"] = new SelectList(_context.Priorities, "Id", "PriorityDescription", serviceRequests.Priority);
            ViewData["RequestType"] = new SelectList(_context.RequestTypes, "Id", "RequestTypeDescription", serviceRequests.RequestType);
            ViewData["RequestTypeStep"] = new SelectList(_context.RequestTypeSteps, "Id", "StepDescription", serviceRequests.RequestTypeStep);
            ViewData["Status"] = new SelectList(_context.StatusSets, "Id", "StatusDescription", serviceRequests.Status);
            ViewData["Team"] = new SelectList(_context.Teams, "Id", "TeamDescription", serviceRequests.Team);
            return View(serviceRequests);
        }

        // GET: ServiceRequests/Edit/5
        public async Task<IActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var serviceRequests = await _context.ServiceRequests.SingleOrDefaultAsync(m => m.Id == id);
            if (serviceRequests == null)
            {
                return NotFound();
            }
            ViewData["Member"] = new SelectList(_context.Members, "Id", "MemberEmail", serviceRequests.Member);
            ViewData["Priority"] = new SelectList(_context.Priorities, "Id", "PriorityDescription", serviceRequests.Priority);
            ViewData["RequestType"] = new SelectList(_context.RequestTypes, "Id", "RequestTypeDescription", serviceRequests.RequestType);
            ViewData["RequestTypeStep"] = new SelectList(_context.RequestTypeSteps, "Id", "StepDescription", serviceRequests.RequestTypeStep);
            ViewData["Status"] = new SelectList(_context.StatusSets, "Id", "StatusDescription", serviceRequests.Status);
            ViewData["Team"] = new SelectList(_context.Teams, "Id", "TeamDescription", serviceRequests.Team);
            return View(serviceRequests);
        }

        // POST: ServiceRequests/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("Id,RequestHeading,RequestDescription,RequestorId,RequestorFirstName,RequestorLastName,RequestorPhone,RequestorEmail,DateTimeSubmitted,DateTimeStarted,DateTimeCompleted,Priority,RequestType,RequestTypeStep,Member,Status,Team")] ServiceRequests serviceRequests)
        {
            if (id != serviceRequests.Id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {

                    // If Status changes then populate the datetime started and completed fields and send email confirmation=========

                    if (serviceRequests.Status == 2 && serviceRequests.DateTimeStarted == null)
                    {
                        serviceRequests.DateTimeStarted = DateTime.Now;
                        SendStatusConfirmation(2, serviceRequests.RequestorEmail);
                        _context.Entry(serviceRequests).State = EntityState.Modified;
                    }

                    if (serviceRequests.Status == 3 && serviceRequests.DateTimeCompleted == null)
                    {
                        serviceRequests.DateTimeCompleted = DateTime.Now;
                        SendStatusConfirmation(3, serviceRequests.RequestorEmail);
                        _context.Entry(serviceRequests).State = EntityState.Modified;

                    }


                    ////===================================================================================



                    // If team is modified create new team history record==========================

                    //var lastTeam = _context.TeamAssignmentHistories
                    //    .Include(t => t.ServiceRequestNavigation)
                    //    .Include(t => t.TeamNavigation)
                    //    .Where(t => t.ServiceRequestNavigation.Id == serviceRequests.Id);
                    var lastTeam = from tah in _context.TeamAssignmentHistories
                                   where tah.ServiceRequest == serviceRequests.Id
                                   orderby tah.DateAssigned descending
                                   select tah;
                    int lteam;
                    lteam = lastTeam.FirstOrDefault().Team;

                    if (serviceRequests.Team != lteam)

                    {
                        serviceRequests.TeamAssignmentHistories.Add(new TeamAssignmentHistories()
                        {
                            DateAssigned = DateTime.Now,
                            AssignedBy = User.Identity.Name,
                            ServiceRequest = serviceRequests.Id,
                            Team = serviceRequests.Team
                        });

                    }

                    //=========================================================================================



                    //=========================================================================================

                    // if individual assigned has changed add individual history record========================
                    //var lastMember = _context.IndividualAssignmentHistories
                    //    .Include(t => t.ServiceRequestNavigation)
                    //    .Where(t => t.ServiceRequestNavigation.Id == serviceRequests.Id)
                    //    ;
                    var lastMember = from lm in _context.IndividualAssignmentHistories
                                     where lm.ServiceRequest == serviceRequests.Id
                                     orderby lm.DateAssigned descending
                                     select lm;
                    int lmember;
                    lmember = lastMember.FirstOrDefault().AssignedTo;

                    if (serviceRequests.Member != lmember)
                    {
                        serviceRequests.IndividualAssignmentHistories.Add(new IndividualAssignmentHistories()
                        {
                            DateAssigned = DateTime.Now,
                            AssignedBy = User.Identity.Name,
                            ServiceRequest = serviceRequests.Id,
                            AssignedTo = serviceRequests.Member.Value,
                        });
                    }


                    //===========================================================================================


                    //===== If request step changes then  create request step history record=====================

                    //var lastStep = _context.StepHistories
                    //    .Include(t => t.ServiceRequestNavigation)
                    //    .Where(t => t.ServiceRequestNavigation.Id == serviceRequests.Id)
                    //    ;
                   var lastStep = from ls in _context.StepHistories
                               where ls.ServiceRequest == serviceRequests.Id
                               orderby ls.LastUpdated descending
                               select ls;
                    int lstep;
                    lstep = lastStep.FirstOrDefault().RequestTypeStep;

                    if (serviceRequests.RequestTypeStep != lstep)
                    {
                        serviceRequests.StepHistories.Add(new StepHistories()
                        {
                            LastUpdated = DateTime.Now,
                            RequestTypeStep = serviceRequests.RequestTypeStep.Value,
                            ServiceRequest = serviceRequests.Id
                        });
                    }

                    //===========================================================================================



                    _context.Update(serviceRequests);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!ServiceRequestsExists(serviceRequests.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index));
            }
            ViewData["Member"] = new SelectList(_context.Members, "Id", "MemberEmail", serviceRequests.Member);
            ViewData["Priority"] = new SelectList(_context.Priorities, "Id", "PriorityDescription", serviceRequests.Priority);
            ViewData["RequestType"] = new SelectList(_context.RequestTypes, "Id", "RequestTypeDescription", serviceRequests.RequestType);
            ViewData["RequestTypeStep"] = new SelectList(_context.RequestTypeSteps, "Id", "StepDescription", serviceRequests.RequestTypeStep);
            ViewData["Status"] = new SelectList(_context.StatusSets, "Id", "StatusDescription", serviceRequests.Status);
            ViewData["Team"] = new SelectList(_context.Teams, "Id", "TeamDescription", serviceRequests.Team);
            return View(serviceRequests);
        }

        // GET: ServiceRequests/Delete/5
        public async Task<IActionResult> Delete(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var serviceRequests = await _context.ServiceRequests
                .Include(s => s.MemberNavigation)
                .Include(s => s.PriorityNavigation)
                .Include(s => s.RequestTypeNavigation)
                .Include(s => s.RequestTypeStepNavigation)
                .Include(s => s.StatusNavigation)
                .Include(s => s.TeamNavigation)
                .SingleOrDefaultAsync(m => m.Id == id);
            if (serviceRequests == null)
            {
                return NotFound();
            }

            return View(serviceRequests);
        }

        // POST: ServiceRequests/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var serviceRequests = await _context.ServiceRequests.SingleOrDefaultAsync(m => m.Id == id);
            _context.ServiceRequests.Remove(serviceRequests);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

        private bool ServiceRequestsExists(int id)
        {
            return _context.ServiceRequests.Any(e => e.Id == id);
        }

        public void GetADinfo(out string givenName, out string surname, out string homePhone, out string email)
        {
            //===========================================================
            //Go and get AD info for the current user or equivalent
            var components = User.Identity.Name.Split('\\');
            var username = components.Last();
            // create LDAP connection object
            DirectoryEntry myLdapConnection = createDirectoryEntry();
            DirectorySearcher search = new DirectorySearcher(myLdapConnection);

            search.Filter = "(cn=" + username + ")";
            SearchResult result = search.FindOne();
            DirectoryEntry dsresult = result.GetDirectoryEntry();
            givenName = dsresult.Properties["givenName"][0].ToString();
            surname = dsresult.Properties["sn"][0].ToString();
            email = dsresult.Properties["mail"][0].ToString();
            homePhone = dsresult.Properties["homePhone"][0].ToString();

            //=============================================================================
        }

        public DirectoryEntry createDirectoryEntry()
        {
            // create and return new LDAP connection with desired settings

            string ADconn = _context.ApplicConfs.Select(s => s.Ldapconn).FirstOrDefault();
            string LDAPConn = _context.ApplicConfs.Select(s => s.Ldappath).FirstOrDefault();

            //string ADconn;
            //ADconn = "SERVER.A3HR.local";
            //string LDAPConn;
            //LDAPConn = "LDAP://SERVER.A3HR.local";
            //DirectoryEntry ldapConnection = new DirectoryEntry("SERVER.A3HR.local");

            //ldapConnection.Path = "LDAP://OU=staffusers,DC=leeds-art,DC=ac,DC=uk";
            //ldapConnection.Path = "LDAP://SERVER.A3HR.local";

            DirectoryEntry ldapConnection = new DirectoryEntry(ADconn);

            ldapConnection.Path = LDAPConn;

            ldapConnection.AuthenticationType = AuthenticationTypes.Secure;

            return ldapConnection;
        }



        public void SendStatusConfirmation(int statusstep, string email)
        {
            var message = new MimeMessage();

            string mailFrom = _context.ApplicConfs.Select(s => s.ManageHremail).FirstOrDefault();
            string fromPass = _context.ApplicConfs.Select(s => s.ManageHremailPass).FirstOrDefault();
            string smtpHost = _context.ApplicConfs.Select(s => s.Smtphost).FirstOrDefault();
            int smtpPort = _context.ApplicConfs.Select(s => s.Smtpport).FirstOrDefault().Value;
            Boolean enabSSL = _context.ApplicConfs.Select(s => s.EnableSsl).FirstOrDefault().Value;


            message.To.Add(new MailboxAddress(email));
            message.From.Add(new MailboxAddress(mailFrom));
            switch (statusstep)
            {
                case 1:
                    message.Subject = "Request received";
                    message.Body = new TextPart("plain") { Text = @"Your request has been received" };
                    break;

                case 2:
                    message.Subject = "Request started";
                    message.Body = new TextPart("plain") { Text = @"Your request has been started" };
                    break;

                case 3:
                    message.Subject = "Request completed";
                    message.Body = new TextPart("plain") { Text = @"Your request has been completed" };
                    break;
            }
            using (var client = new MailKit.Net.Smtp.SmtpClient())
            {
                {
                    // For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
                    client.ServerCertificateValidationCallback = (s, c, h, e) => true;



                    client.Connect(smtpHost, smtpPort, false);

                    // Note: since we don't have an OAuth2 token, disable
                    // the XOAUTH2 authentication mechanism.
                    client.AuthenticationMechanisms.Remove("XOAUTH2");

                    // Note: only needed if the SMTP server requires authentication
                    client.Authenticate(mailFrom, fromPass);

                    client.Send(message);
                    client.Disconnect(true);
                }
            }

        }
...