0

I have a context called companyContext. There are Three tables Reports, Logs and Employees. I'm trying to add another Employee to my table of employees, but I have a table Reports that keeps track of which employees belong to cases (CaseID) and if there is a log of what happened. After I add the employee to the context I need to add a Report with the just added employee id (which is a primary key, so its not getting passed with the employee variable). The only way I can think of doing it is getting a current count of the employees table. This seems like bad practice. Is there a better way to achieve this?
Clarify:
I'm sending a Employee employee object from my client. Name and Code are the only things not null in the object.

public async Task<IActionResult> addEmployee([FromBody] Employee employee) {
    try {
        context.Employees.Add(employee);
        var c = storage.GetCase(employee); 
        var employeeId =  await context.Employees.CountAsync(); 
        var report = new Report {
            CaseID = c.Id, 
            EmployeeID = employeeId, 
        }; 
        context.Reports.Add(report); 
        return Json(employee); 
    } catch (Exception ex){
        logger.LogError("Employee exception in Company Controller", ex); 
        return BadRequest("Unexpected Error"); 
    }
}

Models

public class Log
{
    public int ID { get; set; }
    public string Input { get; set; }
    public string Tag { get; set; }
    public DateTime LogDate { get; set; }
    public ICollection<Report> Reports { get; set; }

}
public class Employee
{
    public int ID { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
    public ICollection<Report> Reports { get; set; }

}
public class Report
{
    public int ID { get; set; }
    public string CaseID { get; set; }
    public int EmployeeID { get; set; }
    public int? LogID { get; set; }
    public Employee Employee { get; set; }
    public Log Log { get; set; }
}

Soultion

public async Task<IActionResult> addEmployee([FromBody] Employee employee) {
    try {
        context.Employees.Add(employee);
        await context.SaveChangesAsync();

        var c = storage.GetCase(employee); 
        var report = new Report {
            CaseID = c.Id, 
            EmployeeID = employee.ID, 
        }; 
        context.Reports.Add(report); 
        await context.SaveChangesAsync()
        return Json("Worked"); 
    } catch (Exception ex){
        logger.LogError("Employee exception in Company Controller", ex); 
        return BadRequest("Unexpected Error"); 
    }
}
AJ_
  • 3,787
  • 10
  • 47
  • 82
  • Does your table has Id field set as auto increment? If so, the Id field will be set with a sequential value automatic after adding. – M. A. Cordeiro Oct 31 '16 at 17:06
  • John, please read the HelpCenter entry on how to correctly use tags: http://stackoverflow.com/help/tagging and why not to force them into the title. Additionally, please use ASP.NET Core related tags `asp.net-core` / `asp.net-core-mvc`/`entity-framework-core` rather than the one for the legacy ASP.NET webstack, so the right people might spot them – Tseng Oct 31 '16 at 17:06

2 Answers2

1

Instead of doing this:

context.Reports.Add(report);

You can do this:

employee.Reports.Add(report);

When the employee record is saved, it will know to set the EmployeeID value in the Report object before it's saved to the database.

You may also need to add this in the Employee object to make sure the Report collection is set:

public Employee()
{
  Reports = new HashSet<Report>();
}
Rono
  • 3,171
  • 2
  • 33
  • 58
  • Is this what you mean => var report = new Report { CaseID = c.Id, }; employee.Reports.Add(report); – AJ_ Oct 31 '16 at 17:43
  • and with context i have to do the save method. Do the tables automatically save with your way? – AJ_ Oct 31 '16 at 18:19
  • Correct, once you do context.SaveChanges(), both the employee and report records will be saved to the database, and the report.EmployeeID will be set to the key for Employee – Rono Oct 31 '16 at 18:20
  • Exception thrown: 'System.NullReferenceException' in Application-Report.dll fail: Application.Controllers.CompanyController[0]. – AJ_ Oct 31 '16 at 18:23
  • Im guess this is because its getting sent from the client, which doesnt have references set to anything. So i could query the employees context for a matching entry and then try your method. – AJ_ Oct 31 '16 at 18:27
  • I'm thinking you need to add this line to the constructor of the Employee object: Reports = new HashSet(); I'll update the answer to include this. – Rono Oct 31 '16 at 18:37
1

try to use it EmployeeId from the saved one, i.e.

var report = new Report {
        CaseID = c.Id, 
        EmployeeID = employee.ID
    }; 

when it is saved it should get the ID directly.

Question, is there any specific reason why you didn't use "virtual methods" in your entities for lazy loading?

And I'd also consider what would happen if context.reports.add(report) failed but employee add hadn't failed.

rkmorgan
  • 487
  • 4
  • 12
  • employee.ID IS 0, since its not set. Also, when its added with that id it becomes -2147482647 [int], i dont know what you are referring to for the virtual comment.t – AJ_ Oct 31 '16 at 18:16
  • I meant having virtual properties to connect tables... You can find details here, http://stackoverflow.com/questions/5597760/what-effects-can-the-virtual-keyword-have-in-entity-framework-4-1-poco-code-fi – rkmorgan Oct 31 '16 at 19:28
  • where do you call SaveChanges()? after that added employee must get an id from Db... P.S.. I am assuming you database table has ID column with auto incremented prop. – rkmorgan Oct 31 '16 at 19:31
  • Yeah its auto increment. Did you see the edit to my question, about it just having the Name and Code members filled. Everything else is null. I call SaveChanges at the very end, however, with your code id is -2147482647. – AJ_ Oct 31 '16 at 21:02
  • for testing, can u call SaveChanges in two locations: 1st just after Adding a new employee, 2nd after adding the report. After calling 1st SaveChanges(), check the employee object whether Id column has anything? – rkmorgan Oct 31 '16 at 21:05
  • Well that is interesting. That seems to have done the trick. I don’t know why, because im not resetting the reference object. – AJ_ Oct 31 '16 at 21:24
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/127068/discussion-between-rkmorgan-and-john). – rkmorgan Oct 31 '16 at 21:24