-1

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

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
neda
  • 1
  • 1
  • 1
    make set public – Serge Feb 19 '22 at 13:48
  • if you mean I use 'set' instead of 'private set',i should say it may solve the problem, but as far as i know, making the properties of entities, private set is one of the rules of designing entities in onion architecture. – neda Feb 19 '22 at 19:24
  • I never heard about onion architecture so I am very curious what happenes if you make setters public? Everything will stop working? Why do you need such a strange architecture then? – Serge Feb 19 '22 at 19:28
  • I think there would be no serious problem if we make them public. but i wanted to know is there any way to insert data to related tables whereas the properties are private set?and maby you know the onion architecture with name clean architecture. there is alot of things about this architecture on the internet.it seperates the concers. – neda Feb 19 '22 at 19:39
  • Obviously you can get data from entity framework using a constructor , just google and you will find, but even after it you will get a lot of another problems. I don't see any sense to make life harder then it is already. – Serge Feb 19 '22 at 19:44
  • :) Thank you for taking your time to answer this question – neda Feb 19 '22 at 19:49

1 Answers1

0

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.

neda
  • 1
  • 1