c# Razor Pages, EF Core, Cómo puedo generar y añadir Child Records a través del Código a un Registro de Padres que aún no se ha añadido utilizando

Estoy usando C# Razor Pages con EF Core 5. No estoy usando MVC en absoluto. Estoy tratando de generar automáticamente registros infantiles (meses del año) para un registro de padres (Año con Fecha de inicio/Fecha de inicio). Mi modelo tiene las relaciones establecidas en ellos:

namespace Seasons.Models
{
    public class AccountYears //Parent Record
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public Guid AccountYearsID { get; set; } 
            

        [Display(Name = "Accounts Year Name"), Required]
        public string AccountYearsName { get; set; }

        [Display(Name = "Start Date"), Required, DataType(DataType.Date)]
        public DateTime DateStart { get; set; }

        [Display(Name = "End Date"), Required, DataType(DataType.Date)]
        public DateTime DateEnd { get; set; }

        //AccountYearsMonths
        public List AccountYearsMonths { get; set; }
    }
}

namespace Seasons.Models // Child Records
{
    public class AccountYearsMonths
    {

        // [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public Guid AccountYearsMonthsID { get; set; }

        [Required]
        public Guid AccountYearsID { get; set; }

        [Display(Name = "Month Name"), Required]
        public string AccountYearsMonthsName { get; set; }

        [Display(Name = "Start Date"), Required, DataType(DataType.Date)]
        public DateTime DateStart { get; set; }

        [Display(Name = "End Date"), Required, DataType(DataType.Date)]
        public DateTime DateEnd { get; set; }

        //AccountsYears
        public AccountYears AccountYears { get; set; }

    }

Y luego mi cuentaAños de crear página - Tenga en cuenta que la página sólo tiene campos para que el padre se complete cuando creo, estoy deseando generar todos los registros infantiles en el código y guardar toda la transacción en una sola pasada.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using MyApplication.Data;
using Seasons.Models;

namespace Seasons.Areas.Setup.Pages.FinanceAccountYears
{
    public class CreateModel : PageModel
    {
        private readonly MyApplication.Data.ApplicationDbContext _context;

        public CreateModel(MyApplication.Data.ApplicationDbContext context)
        {
            _context = context;
//            _context.Attach(AccountYearsMonths);
        }

        public IActionResult OnGet()
        {
            return Page();
        }

        [BindProperty]
        public AccountYears AccountYears { get; set; }
        public List AccountYearsMonths { get; set; }

        // public List AccountYearsMonths { get; set; }


        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://aka.ms/RazorPagesCRUD.
        public async Task OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            

            //AccYearsMonths();

            //var emptyAccountYears = new AccountYears();
            //if (await TryUpdateModelAsync(
            //        emptyAccountYears,
            //        "AccYears",
            //        ay => ay.AccountYearsID, ay => ay.AccountYearsName, ay => ay.DateStart, ay => ay.DateEnd, ay => ay.Status))
            //{
            //    _context.AccountYears.Add(emptyAccountYears);

            AccYearsMonths();

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

            //Guid AddedID = AccountYears.AccountYearsID;

            //AccYearsMonths(AddedID);

            //_context.AccountYears.Update(AccountYears);
            //await _context.SaveChangesAsync();

            return RedirectToPage("./Index");
        }


        public void AccYearsMonths()
        {

            // AccountYearsMonths = new List();

            DateTime MasterStartDate = AccountYears.DateStart;
            DateTime MasterEndDate = AccountYears.DateEnd;
            
            // Get the StartDate, MonthEndDate, and YearEndDate into variables

            DateTime Date1 = new DateTime(MasterStartDate.Year, MasterStartDate.Month, 01);
            DateTime Date2 = new DateTime(Date1.Year, Date1.Month, DateTime.DaysInMonth(Date1.Year, Date1.Month));
            string MonthName = new string(Date1.ToString("MMM"));
            

            while (Date1 < MasterEndDate)
                {

                AccountYears.AccountYearsMonths.Add(new AccountYearsMonths
                {
                    AccountYearsMonthsName = MonthName,
                    DateStart = Date1,
                    DateEnd = Date2,
                    Status = "OPEN"
                });

                //AccountYearsMonths d = new AccountYearsMonths
                //{
                //    AccountYearsMonthsName = MonthName,
                //    DateStart = Date1,
                //    DateEnd = Date2,
                //    Status = "OPEN",
                //    AccountYearsID = YearID

                //};

                // _context.AccountYearsMonths.Add(d);
                // AccountYearsMonths.Add(d);


                if (Date1.Month > 11)
                {
                    Date1 = new DateTime(Date1.Year + 1, 01, 01);
                }
                else
                {
                    Date1 = new DateTime(Date1.Year, Date1.Month + 1, 01);
                } // Endif
              
                Date2 = new DateTime(Date1.Year, Date1.Month, DateTime.DaysInMonth(Date1.Year, Date1.Month));
                MonthName = Date1.ToString("MMM");

            } // End While

           

        } //End AccYearMonths


    }
}

Tengo el siguiente error cuando ejecuto este código: System.NullReference Excepción: "La referencia objetiva no se establece en una instancia de un objeto". Lo que ocurre cuando se ejecuta esta línea: AccountYears.AccountYearsMonths.Add(new AccountYearsMonths

Como puedes ver por todo el código comentado he probado algunas maneras diferentes.

Cualquier ayuda sería muy apreciada.

Pregunta hecha hace 3 años, 4 meses, 29 días - Por codemasterx


3 Respuestas:

  • Necesitas inicializar AccountYearsMonths objeto como abajo:

    while (Date1 < MasterEndDate)
    {
         //change here...
        AccountYears.AccountYearsMonths = new List();
    
        AccountYears.AccountYearsMonths.Add(new AccountYearsMonths
        {
            AccountYearsMonthsName = MonthName,
            DateStart = Date1,
            DateEnd = Date2,
            Status = "OPEN"
        });
        //....
    }
    

    Resultado:

    enter image description here

    Respondida el Dec 17, 2020 a las 22:57 - por webweaverx

    Votos positivos: 0 | Votos negativos: 0

  • El error "NullReference Exception" indica que estás intentando acceder a una referencia de un objeto que no ha sido inicializada. En este caso, en el método AccYearsMonths(), el error se produce en la línea donde intentas agregar un nuevo AccountYearsMonths a la lista AccountYears.AccountYearsMonths.

    La razón de este error es que la propiedad AccountYearsMonths de la clase AccountYears no ha sido inicializada antes de intentar agregar elementos a ella. Para solucionar este problema, necesitas inicializar la lista antes de agregar elementos. Puedes hacerlo de la siguiente manera:

    csharp
    public void AccYearsMonths()
    {
        AccountYears.AccountYearsMonths = new List(); // Inicializa la lista antes de agregar elementos
    
        DateTime MasterStartDate = AccountYears.DateStart;
        DateTime MasterEndDate = AccountYears.DateEnd;
    
        DateTime Date1 = new DateTime(MasterStartDate.Year, MasterStartDate.Month, 01);
        DateTime Date2 = new DateTime(Date1.Year, Date1.Month, DateTime.DaysInMonth(Date1.Year, Date1.Month));
        string MonthName = new string(Date1.ToString("MMM"));
    
        while (Date1 < MasterEndDate)
        {
            AccountYears.AccountYearsMonths.Add(new AccountYearsMonths
            {
                AccountYearsMonthsName = MonthName,
                DateStart = Date1,
                DateEnd = Date2,
                Status = "OPEN"
            });
    
            if (Date1.Month > 11)
            {
                Date1 = new DateTime(Date1.Year + 1, 01, 01);
            }
            else
            {
                Date1 = new DateTime(Date1.Year, Date1.Month + 1, 01);
            } 
    
            Date2 = new DateTime(Date1.Year, Date1.Month, DateTime.DaysInMonth(Date1.Year, Date1.Month));
            MonthName = Date1.ToString("MMM");
        }
    }
    

    Al agregar AccountYears.AccountYearsMonths = new List<AccountYearsMonths>(); al principio del método, te aseguras de que la lista esté inicializada antes de intentar agregar elementos a ella, lo que debería evitar el error de "NullReference Exception".

    Espero que esta solución te ayude a corregir el error y que puedas continuar con el desarrollo de tu aplicación. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 18, 2020 a las 22:56 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El error System.NullReferenceException ocurre porque la propiedad AccountYearsMonths es null cuando intentas añadir nuevos registros AccountYearsMonths a ella. Esto puede suceder si no has inicializado la propiedad AccountYearsMonths antes de intentar añadirle elementos.

    Para solucionar este problema, debes inicializar la propiedad AccountYearsMonths como una nueva lista antes de intentar añadirle elementos. Puedes hacerlo añadiendo el siguiente código al principio del método AccYearsMonths():

    c

    AccountYears.AccountYearsMonths = new List();

    Esto creará una nueva lista vacía para la propiedad AccountYearsMonths y permitirá que se añadan nuevos elementos sin errores.

    Aquí tienes el método AccYearsMonths() actualizado con la inicialización añadida:

    c

    public void AccYearsMonths()

    { AccountYears.AccountYearsMonths = new List(); DateTime MasterStartDate = AccountYears.DateStart; DateTime MasterEndDate = AccountYears.DateEnd; // Get the StartDate, MonthEndDate, and YearEndDate into variables DateTime Date1 = new DateTime(MasterStartDate.Year, MasterStartDate.Month, 01); DateTime Date2 = new DateTime(Date1.Year, Date1.Month, DateTime.DaysInMonth(Date1.Year, Date1.Month)); string MonthName = new string(Date1.ToString("MMM")); while (Date1 < MasterEndDate) { AccountYears.AccountYearsMonths.Add(new AccountYearsMonths { AccountYearsMonthsName = MonthName, DateStart = Date1, DateEnd = Date2, Status = "OPEN" }); //AccountYearsMonths d = new AccountYearsMonths //{ // AccountYearsMonthsName = MonthName, // DateStart = Date1, // DateEnd = Date2, // Status = "OPEN", // AccountYearsID = YearID //}; // _context.AccountYearsMonths.Add(d); // AccountYearsMonths.Add(d); if (Date1.Month > 11) { Date1 = new DateTime(Date1.Year + 1, 01, 01); } else { Date1 = new DateTime(Date1.Year, Date1.Month + 1, 01); } // Endif Date2 = new DateTime(Date1.Year, Date1.Month, DateTime.DaysInMonth(Date1.Year, Date1.Month)); MonthName = Date1.ToString("MMM"); } // End While } //End AccYearMonths

    También es importante asegurarte de que estás utilizando el contexto de base de datos correcto para guardar los cambios. En tu código, estás utilizando _context.AccountYears para añadir el registro AccountYears, pero no estás guardando los cambios en la base de datos. Para guardar los cambios, debes llamar a SaveChangesAsync() en el contexto después de añadir el registro.

    Aquí tienes el método OnPostAsync() actualizado con la llamada a SaveChangesAsync():

    c

    public async Task OnPostAsync()

    { if (!ModelState.IsValid) { return Page(); } AccYearsMonths(); _context.AccountYears.Add(AccountYears); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); }

    Con estos cambios, tu código debería poder generar y añadir registros AccountYearsMonths a un registro AccountYears que aún no se ha añadido utilizando el código, y guardar todos los cambios en una sola pasada.

    Respondida el Dec 18, 2020 a las 23:00 - por Gemini

    Votos positivos: 0 | Votos negativos: 0