Reputation: 2959
I work with Entity Framework. Here is examples of my SQL tables :
RPM_Data
RPM_ID Year Month Budget_Code Code_IAM Actual_Days Direction_ID Cost
1 2014 1 03-G317 S00140802 0,03125 7 5,5
2 2014 2 01-G001 S00220105 0,01525 6 2,5
3 2014 3 01-G001 S00140802 0,05015 5 10
Direction
Id Label
5 Direction_n1
6 Direction_n2
7 Direction_n3
I need to get the sum of each "Actual_Days" per Budget_Line, Code_IAM and Direction for all the year. So it looks like a list of objects like this :
BudgetCode : "03-G317"
Code_IAM : "S00140802"
Direction : "Direction_n3"
ActualJan : 0.325
ActualFeb : 1.25
ActualMar : 1.325
ActualApr : 0.75
ActualMay : 3.25
ActualJun : 2.325
ActualJul : 4.25
ActualAug : 1.125
ActualSep : 0.22
ActualOct : 0.325
ActualNov : 2.325
ActualDec : 4.325
Cost : 12554.25
So I come up with the following query :
var directions = db.Direction.ToList();
List<Actual> query = (from r in db.RPM_Data
where r.Year == DateTime.UtcNow.Year && lines.Contains(r.Budget_Code)
group r by new { r.Budget_Code, r.Code_IAM, r.Direction_ID } into grp
select
new Actual
{
BudgetLine = grp.Key.Budget_Code,
CodeIam = grp.Key.Code_IAM,
Direction = db.Direction.Where(d => d.Id == grp.Key.Direction_ID)
.Select(d => d.Label)
.FirstOrDefault(),
ActualJan = grp.Sum(x => x.Month == 1 ? x.Actual_Days : 0),
ActualFeb = grp.Sum(x => x.Month == 2 ? x.Actual_Days : 0),
ActualMar = grp.Sum(x => x.Month == 3 ? x.Actual_Days : 0),
ActualApr = grp.Sum(x => x.Month == 4 ? x.Actual_Days : 0),
ActualMay = grp.Sum(x => x.Month == 5 ? x.Actual_Days : 0),
ActualJun = grp.Sum(x => x.Month == 6 ? x.Actual_Days : 0),
ActualJul = grp.Sum(x => x.Month == 7 ? x.Actual_Days : 0),
ActualAug = grp.Sum(x => x.Month == 8 ? x.Actual_Days : 0),
ActualSep = grp.Sum(x => x.Month == 9 ? x.Actual_Days : 0),
ActualOct = grp.Sum(x => x.Month == 10 ? x.Actual_Days : 0),
ActualNov = grp.Sum(x => x.Month == 11 ? x.Actual_Days : 0),
ActualDec = grp.Sum(x => x.Month == 12 ? x.Actual_Days : 0),
Cost = grp.Sum(x => x.Cost)
}
).ToList();
But the sub-query with db.Direction
destroys my performance...
So I tried to "store" all my db.Direction
first and get the Id from it later.
var directions = db.Direction.ToList();
// And then in my query
// ...
Direction = directions.Where(d => d.Id == grp.Key.Direction_ID)
.Select(d => d.Label)
.FirstOrDefault(),
// ...
But I get the following error :
Unable to create a constant value of type 'OPManager.DataAccess.Direction'. Only primitive types or enumeration types are supported in this context.
I also tried without .ToList()
and get an error to.
Can you tell me what is the proper way to handle this foreign key in my query?
How can I have the best performance in order to get what I want?
Upvotes: 0
Views: 65
Reputation: 14640
Try to set the Direction
property later after ToList
, but store the Direction_ID
temporary.
public class Action
{
[NotMapped]
public int Direction_ID { get; set; }
}
The query.
List<Actual> query = (from r in db.RPM_Data
where r.Year == DateTime.UtcNow.Year && lines.Contains(r.Budget_Code)
group r by new { r.Budget_Code, r.Code_IAM, r.Direction_ID } into grp
select
new Actual
{
BudgetLine = grp.Key.Budget_Code,
CodeIam = grp.Key.Code_IAM,
//Direction = ... -> leave this property unset.
Direction_ID = grp.Key.Direction_ID, // but set the id.
}
).ToList();
Then set the direction.
foreach(var a in query)
{
a.Direction = directions.Where(d => d.Id == a.Direction_ID)
.Select(d => d.Label)
.FirstOrDefault();
// Hides the direction id if necessary.
a.Direction_ID = 0;
}
Upvotes: 1