Jimbo
Jimbo

Reputation: 113

Breezejs/knockout - how do you combine entities?

I am very new to breeze.js and I need to be able to combine two entities.

Right now I cannot get all of the information I need in one query. My solution is to get both entities separately and then combine in code.

Here are the two queries:

         var query = breeze.EntityQuery
        .from("EmployeeLaborTasks")
        .where("task_ID", "==", taskID)
        .orderBy("employee_ID")
        .expand(["Employee", "LaborCategory"]);


         var query = breeze.EntityQuery
        .from("ForecastedHours")
        .where("task_ID", "==", taskID)
        .expand("Employee");

EmployeeLaborTasks is a join table with foreign keys for the taskID, employeeID and LaborCategoryID. This allows me to load the Employees and their LaborCategories based on the taskID.

However, I still need each employee's forecastedHours. . .

ForecastedHours are entered by month, so an employee could have many entries over the year (12 max). Because of this, there is no applicable navigation property that I can use to add ForecastedHours to the first query. This table contains a foreign key for taskID and employeeID. Thus, a 2nd one is necessary.

I would like to join these two resulting entities on employee.ID. Ultimately, I will use this information in a grid (via knockout/Durandal), displaying the employee name, labor category, and forecast hours over 12 months.

Is this possible? Will joining these entities ruin any Breeze.js tracking that makes the info updateable?

I am also wondering if it would be better to combine them via knockout's ko.computed but I am not sure how to do this.

Any help would be greatly appreciated.


In response to Dominictus below, I am posting the data models for the tables in question:

public class Employee : Person
{
    [Key]
    public int ID { get; set; }
    public string CompanyEmployeeID { get; set; }
    public decimal Salary { get; set; }
    public decimal UtilizationTarget { get; set; }
    public virtual Office OfficeLocation { get; set; }
    public virtual Department Department { get; set; }
    public virtual JobGrade JobGrade { get; set; } 
}



public class EmployeeLaborTasks
{
    [Key]
    public int ID { get; set; }

    public virtual Employee Employee { get; set; }
    [ForeignKey("Employee")]
    public int Employee_ID { get; set; }

    public virtual Task Task { get; set; }
    [ForeignKey("Task")]
    public int Task_ID { get; set; }

    public virtual LaborCategory LaborCategory { get; set; }
    [ForeignKey("LaborCategory")]
    public int LaborCategory_ID { get; set; }
}


public class ForecastedHours
{
    [Key]
    public int ID { get; set; }
    [Required]
    public double Hours { get; set; }
    [Required]
    public DateTime Date { get; set; }

    [Timestamp]
    public Byte[] LastModified { get; set; }
    public virtual User ModifiedBy { get; set; }

    public virtual Employee Employee { get; set; }
    public virtual Task Task { get; set; }

    [ForeignKey("Task")]
    public int Task_ID { get; set; }

    [ForeignKey("Employee")]
    public int Employee_ID { get; set; }
}


public class Task
{
    [Key]
    public int ID { get; set; }
    [Required]
    public string Name { get; set; }
    public int Number { get; set; }

    [ForeignKey("Contract")]
    public int ContractID { get; set; }

    public virtual Contract Contract { get; set; }

    [Timestamp]
    public Byte[] LastModified { get; set; }
    public virtual User ModifiedBy { get; set; }
}


public class LaborCategory
{
    [Key]
    public int ID { get; set; }
    [Required]
    public string Name { get; set; }
    public decimal Rate { get; set; }
    public virtual Contract Contract { get; set; }
    [Timestamp]
    public Byte[] LastModified { get; set; }
    public virtual User ModifiedBy { get; set; }
}

Upvotes: 1

Views: 692

Answers (1)

Dominictus
Dominictus

Reputation: 721

Breeze is a bit more powerful than this and can do it the way you want.

In BreezeController make:

[HttpGet]
public IQueryable<EmployeeLaborTasks> NameHere(){
    return _contextProvider.Context.EmployeeLaborTasks.Include("Employee").Include("LaborCategory").Include("Employee.ForecastedHours");
}

I will assume Employee has

public virtual <ForecastedHour> ForecastedHours {get;set;}

and also that EmployeeLaborTasks (this is just for employee, it should be defined for all other connections) has

public int EmployeeId {get;set;}
[ForeignKey("EmployeeId")]
public Employee Employee {get;set;}

After that you can write only one query on client:

var query = breeze.EntityQuery
    .from("NameHere")
    .where("task_ID", "==", taskID)
    .orderBy("employee_ID")

You put all that into one observable variable. To place it into grid, you would do something like this (pseudo-code here):

foreach employeeLaborTasks as singleTask{
   display (singleTask.employee.name)
   display (singleTask.laborCategory.name)
   foreach (singleTask.employee.forecastedHours as singleForecast){
      display (singleForecast.name)
   }
   display (newline)
}

Upvotes: 2

Related Questions