Home > other >  Ef Core saving Employee entity Throw Cannot insert the value NULL into column ' ' table Jo
Ef Core saving Employee entity Throw Cannot insert the value NULL into column ' ' table Jo

Time:04-12

In my application I am using unit of work and repository pattern and auto mapper
This is the employeeDto

public partial class EmployeeDto
{
public string IdEmployee { get; set; }
public string FirstNameEmployee { get; set; }
public string LastNameEmployee { get; set; }
public int? FkDepartment { get; set; }
public int? FkJobTitle { get; set; }
public string Department { get; set; }
public string JobTitle { get; set; }

public virtual DepartmentDto FkDepartmentNavigationDto { get; set; }
public virtual JobTitleDto FkJobTitleNavigationDto { get; set; }
}

And this JobTitleDto

public partial class JobTitleDto
 {
    public JobTitleDto()
    {
        EmployeesDto = new HashSet<EmployeeDto>();
    }

    public int IdJobTitle { get; set; }
    public string NameJobTitle { get; set; }

    public virtual ICollection<EmployeeDto> EmployeesDto { get; set; }
 }

this is the code generated by EF Core

    public void Configure(EntityTypeBuilder<Employee> entity)
    {
        entity.Property(e => e.FkDepartment).HasColumnName("FK_Department");

        entity.Property(e => e.FkJobTitle).HasColumnName("FK_JobTitle");

        entity.HasOne(d => d.FkDepartmentNavigation)
            .WithMany(p => p.Employees)
            .HasForeignKey(d => d.FkDepartment)
            .HasConstraintName("FK_Employee_Department");

        entity.HasOne(d => d.FkJobTitleNavigation)
            .WithMany(p => p.Employees)
            .HasForeignKey(d => d.FkJobTitle)
            .HasConstraintName("FK_Employee_JobTitle"); 

        OnConfigurePartial(entity);
    }

in JobTitleService I get all JobTitle like this

 public class JobTitleService: BaseService
{
    public JobTitleService(IUnitOfWork unitOfWork, IMapper mapper):base(unitOfWork, mapper)
    {

    }
    public async Task<IEnumerable<JobTitleDto>> GetAllJobTitlesAsync()
    {
        var jobTitle = await unitOfWork.JobTitles.GetAllAsync();
        return mapper.Map<IEnumerable<JobTitleDto>>(jobTitle);
    }
}

And this is how I get and added employees

public EmployeeService(IUnitOfWork unitOfWork, IMapper mapper):base(unitOfWork, mapper)
{

}
public async Task<IEnumerable<EmployeeDto>> GetAllEmployeesDetailsAsync()
{
    var employee = await unitOfWork.Employees.GetAllIncluding(
                    emp => emp.FkCountryNavigation,
                    emp => emp.FkDepartmentNavigation,
                    emp => emp.FkGenderNavigation,
                    emp => emp.FkJobTitleNavigation,
                    emp => emp.FkMaritalStatusNavigation,
                    emp => emp.FkProvincesNavigation,
                    emp => emp.FkTownNavigation);
    return mapper.Map<IEnumerable<EmployeeDto>>(employee);
}
public async Task<bool> InsertEmployeeAsync(EmployeeDto employeeDto)
{
    var employee = mapper.Map<Employee>(employeeDto);
    return await unitOfWork.Employees.AddAsync(employee);
}

and this is the code behind the employee form

    private BindingSource listEmployeeDto = new();
private readonly EmployeeService employeeService;
private readonly DepartmentService departmentService;
private readonly JobTitleService jobTitleService;

public FrmEmployee(EmployeeService employeeService, 
                   DepartmentService departmentService,
                   JobTitleService jobTitleService)
{
    InitializeComponent();
    this.employeeService = employeeService;
    this.departmentService = departmentService;
    this.jobTitleService = jobTitleService;
}
 private async void btnSave_Click(object sender, EventArgs e)
{
    var employeeDto = listEmployeeDto.Current as EmployeeDto;
    await employeeService.InsertEmployeeAsync(employeeDto);
    await employeeService.CompleteAsync();
}
private async Task LoadDataAsync()
{
    listEmployeeDto.DataSource = await employeeService.GetAllEmployeesDetailsAsync();
    gridControl1.DataSource = listEmployeeDto;

    cmbJobtitle.Properties.DataSource = await jobTitleService.GetAllJobTitlesAsync();
    cmbJobtitle.Properties.DisplayMember = "NameJobTitle";
    cmbJobtitle.Properties.ValueMember = "IdJobTitle";

    cmbDepartment.Properties.DataSource = await departmentService.GetAllDepartmentsAsync();
    cmbDepartment.Properties.DisplayMember = "NameDepartment";
    cmbDepartment.Properties.ValueMember = "IdDepartment";
}
private void BindingControls()
{
    var employeeDto = listEmployeeDto.Current as EmployeeDto;
    txtUserID.DataBindings.Add(new Binding("EditValue", listEmployeeDto, nameof(employeeDto.IdEmployee)));
    txtFirstName.DataBindings.Add(new Binding("EditValue", listEmployeeDto, nameof(employeeDto.FirstNameEmployee)));
    txtLastName.DataBindings.Add(new Binding("EditValue", listEmployeeDto, nameof(employeeDto.LastNameEmployee)));
    cmbJobtitle.DataBindings.Add(new Binding("EditValue", listEmployeeDto, nameof(employeeDto.FkJobTitle), true, DataSourceUpdateMode.OnPropertyChanged));
    cmbDepartment.DataBindings.Add(new Binding("EditValue", listEmployeeDto, nameof(employeeDto.FkDepartment),true,DataSourceUpdateMode.OnPropertyChanged));
}

There is no problem when I edited or deleted employees
but when I add new employee I get this error

Inner Exception 1: SqlException: Cannot insert the value NULL into column 'Name_JobTitle', table 'SIM.dbo.JobTitle'; column does not allow nulls. INSERT fails.

In JobTitle form I can perform CRUD operations without any problems
this is the full StackTrace

Microsoft.EntityFrameworkCore.DbUpdateException
  HResult=0x80131500
  Message=An error occurred while saving the entity changes. See the inner exception for details.
  Source=Microsoft.EntityFrameworkCore.Relational
  StackTrace:
   at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.<ConsumeAsync>d__2.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.<ExecuteAsync>d__29.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.<ExecuteAsync>d__29.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__103.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__107.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.<ExecuteAsync>d__7`2.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__60.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__60.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Persistence.EFCore.UnitOfWork.<CompleteAsync>d__47.MoveNext() in C:\Users\MBoua\source\repos\SmartWinForm\DataAccess.EFCore\UnitOfWork.cs:line 42
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Application.Service.EmployeeService.<CompleteAsync>d__7.MoveNext() in C:\Users\MBoua\source\repos\SmartWinForm\Application\Service\EmployeeService.cs:line 60
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at SmartWinForm.PL.FrmEmployee.<btnSave_Click>d__29.MoveNext() in C:\Users\MBoua\source\repos\SmartWinForm\SmartWinForm\PL\FrmEmployee.cs:line 290

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
SqlException: Cannot insert the value NULL into column 'Name_JobTitle', table 'SIM.dbo.JobTitle'; column does not allow nulls. INSERT fails.

Update

public partial class JobTitle
{
    public JobTitle()
    {
        Employees = new HashSet<Employee>();
    }

    public int IdJobTitle { get; set; }
    public string NameJobTitle { get; set; }

    public virtual ICollection<Employee> Employees { get; set; }
}
public partial class Employee
{
    public string IdEmployee { get; set; }
    public string FirstNameEmployee { get; set; }
    public string LastNameEmployee { get; set; }
    public int? FkDepartment { get; set; }
    public int? FkJobTitle { get; set; }

    public virtual Department FkDepartmentNavigation { get; set; }
    public virtual JobTitle FkJobTitleNavigation { get; set; }
}

CodePudding user response:

The problem is when you map the Dto to Employee the FkJobTitleNavigation will be evaluated, and when try to adding an entity with child (in this case is JobTitle) EF try to add child after parent inserted (parent is employee) so all you need to solve your problem is remove the child like this:

var employee = mapper.Map<Employee>(employeeDto); 
employee.FkJobTitleNavigation =null;  
return await unitOfWork.Employees.AddAsync(employee);
  • Related