简体   繁体   中英

How to save data in related tables in many-to-many in .NET Core when the entities are protected and properties are private set in onion architecture?

I have the following entities:

LawFAQ entity:

namespace HW_R2.Domain.LawFAQAgg
{
        public class LawFAQ
        {
            public int Id { get; private set; }
            public string Question { get; private set; }
            public string Answer { get; private set; }
            public bool IsDeleted { get; private set; }
            public DateTime  CreationDate { get; private set; }
    
            // For n*1 relationship between LawFAQ and LawFaqLawCategory
            public List<LawFAQLawCategory> LawFAQLawCategories { get; private set; }
    
            protected LawFAQ()
            {       
            }
    
            public LawFAQ(string question, string answer)
            {
                Question = question;
                Answer = answer;
                IsDeleted = false;
                CreationDate = DateTime.Now;                                      
            }
                   
            public void Activate()
            {
                IsDeleted = false;
            }
    
            public void Remove()
            {
                IsDeleted = true;
            }
    
            public void Edit(string question, string answer)
            {
                Question = question;
                Answer = answer;
            }
        }
}
    
    

LawCategory entity:

namespace HW_R2.Domain.LawCategoryAgg
{
        public class LawCategory
        {
            public int Id { get; private set; }
            public string Title { get; private set; }
            public string ShotDesc { get; private set; }
            public string FullContDesc { get; private set; }        
            public string Img { get; private set; }
            public bool IsDeleted { get; private set; }
            public DateTime CreationDate { get; private set; }
                         
           // For n*1 relationship between LawCategory and LawFAQLawCategory
            public List<LawFAQLawCategory> LawFAQLawCategories { get; private set; }                      
    
            protected LawCategory()
            {
            }      
            
            public LawCategory(string title, string shortDesc, string fullContDesc, string img)
            {
                Title = title;
                ShotDesc = shortDesc;
                FullContDesc = fullContDesc;
                Img = img;
                IsDeleted = false;
                CreationDate = DateTime.Now;
            }                     
        }
}
     

And LawFAQLawCategory entity:

namespace HW_R2.Domain.LawFAQLawCategoryAgg
{
    public class LawFAQLawCategory
    {
        public int LawFAQId { get; private set; }
        public LawFAQ LawFAQ { get; private set; }

        public int LawCategoryId { get; private set; }
        public LawCategory LawCategory { get; private set; }

        protected LawFAQLawCategory()
        {    
        }

        public LawFAQLawCategory(int lawFAQId,int lawCategoryId)
        {
            LawFAQId =lawFAQId;
            LawCategoryId = lawCategoryId;
        }    
    }
}

The LawFAQApplication is:

using HW_R2.Application.Contracts.LawFAQ;
using HW_R2.Domain.LawFAQAgg;
using System.Collections.Generic;

namespace HW_R2.Application
{
    public class LawFAQApplication:ILawFAQApplication
    {
        private readonly ILawFAQRepository _lawFAQRepository;

        public LawFAQApplication(ILawFAQRepository lawFAQRepository)
        {
            _lawFAQRepository = lawFAQRepository;
        }
            
        public void Create(Create command)
        {
             //_lawFAQRepository.Create(new LawFAQ(command.Question,command.Answer));
            _lawFAQRepository.Create(command);
        }
    }
}

And the LawFAQRepository is:

using HW_R2.Application.Contracts.LawFAQ;
using HW_R2.Domain.LawFAQAgg;
using HW_R2.Domain.LawFAQLawCategoryAgg;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace HW_R2.Infrastracture.EFCore.Repositories
{
    public class LawFAQRepository: ILawFAQRepository
    {
        private readonly HamedWebsire_Refac2Context _context;

        public LawFAQRepository(HamedWebsire_Refac2Context context)
        {
            _context = context;
        }

        // public void Create(LawFAQ entity)
        public void Create(Create command)
        {
            var entity = new LawFAQ(command.Question, command.Answer);
             _context.LawFAQs.Add(entity);           
            
            foreach (var item in command.LawCategoryIds)
            {
                entity.LawFAQLawCategories.Add(new LawFAQLawCategory(entity.Id, item));
            }

            //PropertyEntry<LawFAQ, int> id = _context.Entry(entity).Property<int>("Id");
            Save();
        }

        public void Save()
        {
            _context.SaveChanges();
        }
    }
}

The problem I have is that on the line (in 'LawFAQRepository')

entity.LawFAQLawCategories.Add(new LawFAQLawCategory(entity.Id, item));

I get an error:

System.NullReferenceException: Object reference not set to an instance of an object

When I check the entity.Id it is 0. I know that the entity hasn't been saved in the database yet, and so it doesn't have the Id. But as I searched, it has been written in link https://stackoverflow.com/questions/17523568/entity-framework-retrieve-id-before-savechanges-inside-a-transaction#:~:text=You%20can%20retreive%20an%20ID,it%20is%20added%20to%20dbcontext .

that before calling SaveChanges() method, we can retrieve the id (which is temporary and will be replaced later). I tested to see it by line

//PropertyEntry<LawFAQ, int> id = _context.Entry(entity).Property<int>("Id");

and I get a negative number as Id. But I don't know why I get an error if the entity.Id is 0 in line

entity.LawFAQLawCategories.Add(new LawFAQLawCategory(entity.Id, item));

in LawFAQRepository .

And another point is that I can't make a new object of these entities from outside because of their protection level. Even I tried to fill the 'LawFAQLawCategories' in LawFAQ entity itself but it has a same error.

Now my question is that how I can save data in LawFAQLawCategory table when I create a new LawFAQ object?

Thank you in advance

I solved the problem by changing the LawFAQRepository to

using HW_R2.Application.Contracts.LawFAQ;
using HW_R2.Domain.LawFAQAgg;
using HW_R2.Domain.LawFAQLawCategoryAgg;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace HW_R2.Infrastracture.EFCore.Repositories
{
    public class LawFAQRepository: ILawFAQRepository
    {
        private readonly HamedWebsire_Refac2Context _context;

        public LawFAQRepository(HamedWebsire_Refac2Context context)
        {
            _context = context;
        }

        public void Create(Create command)
        {

           
            var entity = _context.LawFAQs.Add(new LawFAQ(command.Question, command.Answer));

            var y = (int)entity.Property("Id").CurrentValue;
            var lawFAQLawCategory = new List<LawFAQLawCategory>();
            
            foreach (var item in command.LawCategoryIds)
            {
                lawFAQLawCategory.Add(new LawFAQLawCategory(y, item));  
            }
             entity.Navigation("LawFAQLawCategories").CurrentValue = lawFAQLawCategory;

            //PropertyEntry<LawFAQ, int> id = _context.Entry(entity).Property<int>("Id");
            Save();
        }
        public void Save()
        {
            _context.SaveChanges();
        }
    }
}

In Question, in 'Create(Create command)' method in 'LawFAQRepository',the entity in line

var entity = new LawFAQ(command.Question, command.Answer);

hasn't been added to context(and in its next line it has been added to context), so it is obvious that its Id is 0.

but in the Answer,the entity is

var entity = _context.LawFAQs.Add(new LawFAQ(command.Question, command.Answer));

so its temporary Id has been produced and we don't get the error.

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