You shouldn't put the logic in the EF models. EF models are just used to map objects to the database tables.
I am thinking you want something like this:
public class SalesProjection
{
public int Id { get; set; }
public string Name { get; set; }
public decimal SalesAmount { get; set; }
public decimal CostofSales { get; set; }
//Mark only the navigation properties with the keyword 'virtual'
public virtual IEnumerable<ProjectionMonth> ProjectionMonths { get; set; }
}
public class ProjectionMonth
{
public int Id { get; set; }
public int SalesProjectionId { get; set; }
public int Month { get; set; }
[ForeignKey("SalesProjectionId ")] //EF attribute to denote foreign key.
public virtual SalesProjection SalesProjection { get; set; }
}
The entity models should not contain any business logic such as calculations (e.g GrossProfit). GrossProfit can be calculated on the fly instead of saving it to the database. All business logic should be done in Data Transfer Objects (DTO). Create another set of models (DTO) that will be used to transform the data based on business rules. These are the models you can return to the client:
public class SalesProjectionDTO
{
public int Id { get; set; }
public string Name { get; set; }
public decimal SalesAmount { get; set; }
public decimal CostofSales { get; set; }
public decimal GrossProfit { get; set; }
}
Then, assuming you are using Entity Framework:
public List<SalesProjectionDTO> GetProjectionsByDateRange(int startMonth, int endMonth)
{
var projections = _context.SalesProjection
.Where(sp => sp.SalesProjectionMonths
.Any(m => m.Month >= startMonth && m.Month <= endMonth))
.Select(sp => new SalesProjectionDTO {
Name = sp.Name,
SalesAmount = sp.SalesAmount,
CostOfSales = sp.CostOfSales,
GrossProfit = sp.SalesAmount - sp.CostOfSales
}).ToList();
return projections;
}
public void SaveProjections(SalesProjectionDTO projection, int startMonth, int endMonth)
{
//check if projection exists
var entity= _context.SalesProjection.Where(sp => sp.Id == projection.Id)
.FirstOrDefault() ?? new SalesProjection();
if (entity== null)
_context.Add(projection);
entity.Name = projection.Name;
entity.SalesAmount = projection.SalesAmount;
entity.CostOfSales = projection.CostOfSames;
for (var i = startMonth; i <= endMonth; i++){
entity.ProjectionMonths.Add(
new ProjectionMonth {
Month = i;
}
}
_context.SaveChanges();
}