I am using Entity Framework and have to query a "Project" property a lot, which has a lot of properties which have to be included in the query, making the query bloated:
var project = await this.ProjectRepository.GetRaw().Where(x => x.ID == id).Include(x => x.Leader).Include(x => x.Users).Include(x => x.Firm).FirstOrDefaultAsync();
Please not that GetRaw() returns a IQueryable
Is there a way to construct some helper method where the "include" portion is added, while I dynamically pass in the rest of the query?
something like that:
public async Task<List<Project>> GetProjects(query)
{
return this.ProjectRepository.GetRaw().Include(x => x.Leader).Include(x => x.Users).Include(x => x.Firm) + query;
}
usage something like that:
public ProjectController
{
public void Test()
{
var result = GetProjects.Where(x => x.ID == 0).FirstOrDefaultAsync();
}
}
I think it should look more like this:
public ObjectQuery<Project> GetProjects()
{
return this.ProjectRepository.GetRaw()
.Include(x => x.Leader)
.Include(x => x.Users)
.Include(x => x.Firm);
}
Usage would look like this then:
var result = GetProjects().Where(x => x.ID == 0).FirstOrDefaultAsync();
You can create the expression as parameter and return it as IQueryable<T> so it can be continued by another query.
public IQueryable<Project> GetProjects(Expression<Func<Project, bool> query)
{
return this.ProjectRepository.GetRaw()
.Include(x => x.Leader)
.Include(x => x.Users)
.Include(x => x.Firm)
.Where(query);
}
Usage.
var project = await GetProjects(x => x.ID == 0).FirstOrDefaultAsync();
Related
I have a simple table which only has 3 columns { id, DateTime, NumberOfCoils }, I need to get the results of the query grouped together by the DateTime with the sum of the NumberOfCoils on that particular date.
return testData.MOCK_DATA.Select(x => new { x.NumberOfCoils, x.DateTime })
.AsEnumerable()
.Where(x => x.DateTime> DateTime.Now.AddDays(-numberOfDays))
.Select(x => new { formattedDate = x.DateTime.ToString("yyyy-MM-dd"), x.NumberOfCoils })
.OrderBy(x => x.formattedDate)
.ToList();
I've looked for solutions here but I couldn't figure out how to solve it. I think that part of what's making it hard for me to find a solution is because I have to do some formatting as well.
I'm pretty new to using EF so I apologize if this is a bad question.
Try this:
return testData.MOCK_DATA.Select(x => new { x.NumberOfCoils, x.DateTime })
.AsEnumerable()
.Where(x => x.DateTime> DateTime.Now.AddDays(-numberOfDays))
.GroupBy(x => x.DateTime)
.Sum(x => x.NumberOfCoils);
You need to actually use GroupBy:
return testData.MOCK_DATA.Where(x => x.DateTime > DateTime.Now.AddDays(-numberOfDays))
.GroupBy(d => d.DateTime)
.Select(dg => new { formattedDate = dg.Key.ToString("yyyy-MM-dd"), NumberOfCoils = dg.Sum(d => d.NumberOfCoils) })
.OrderBy(x => x.formattedDate)
.ToList();
The code below is not working. I am getting exception "The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties."
What im doing wrong
public static MyEntity GetData(this IQueryable<MyEntity> source, int id, int year)
{
return source.Where(x => x.ID == id)
.Include(x => x.Childrens1)
.Include(x => x.Childrens2.where(y => y.Year == year))
.FirstOrDefault();
}
Where is not supported into Include expression, you only can use select, even nested. move where out of include
public static MyEntity GetData(this IQueryable<MyEntity> source, int id, int year)
{
return source
.Include(x => x.Childrens1)
.Include(x => x.Childrens2)
.Where(x => x.ID == id && x.Childrens2.Any(y => y.Year == year))
.FirstOrDefault();
}
Now, you also can unify where or filter inside FirstOrDefault
I have table structure like
Product {List<Cost> Costs}
Cost{List<Invoice> Invoices, Product product}
Invoice{bool isIncluded}
Need a query to get all Products which has any Cost for which none of invoice is included (isIncluded=false for all)
I tried something like:
Product pro= null;
Product p = null;
var costQuery = QueryOver.Of<Cost>()
.JoinAlias(c => c.Product, () => p)
.Where(() => p.Id == pro.Id)
.WhereNot(c=>c.Invoices.Any(i=>i.IsIncluded))
.Select(c => c.Id);
var query = CurrentSession.QueryOver<Product>(() => pro)
.WithSubquery.WhereExists(costQuery);
Use of 'Any' in query errors out:
Unrecognised method call: System.Linq.Enumerable:Boolean
Any[Invoice](System.Collections.Generic.IEnumerable1[Trigger.StageGate.Services.BusinessEntities.Invoice],
System.Func2[Trigger.StageGate.Services.BusinessEntities.Invoice,System.Boolean])
try:
var costQuery = QueryOver.Of<Cost>()
.JoinAlias(c => c.Product, () => p)
.Where(() => p.Id == pro.Id)
.JoinQueryOver<Invoice>(c => c.Invoices)
.WhereNot(i => i.IsIncluded)
.Select(c => c.Id);
I get the following error:
"A fetch request must be a simple member access expression; '[100002]' is a SubQueryExpression instead. Parameter name: relatedObjectSelector"
Below is my query:
var query =
session.Query<Customer().Where(cus => cus.CustomerId == customerId)
.Fetch(c => c.CustomerType) // Parent CustomerType
.Fetch(c => c.CustomerOrders) // Child Collection of orders
.ThenFetch(co => co.Select(it => it.Item)).ToList(); // A parent of CustomerOrder
If I take the 'ThenFetch' out then I do not get that error. However, I do need to retrieve the Item object.
Any ideas?
Thanks
Can't you just apply the select on the resulting CustomerOrder?
var query =
session.Query<Customer().Where(cus => cus.CustomerId == customerId)
.Fetch(c => c.CustomerType)
.Fetch(c => c.CustomerOrder)
.Select(co => co.Item)
.ToList();
In the code below I'd like to do a sum for OBFY and CFY separately within each grouping in deptGroup. Anyone have any ideas, I've tried a coupla things but can't get it. Thanks!!
var deptGroup = prodCostsTotals.AsQueryable()
.Select(r => dt.Rows.Add(new object[]
{
Convert.ToInt32(r.Field<string>("Proc")),
r.Field<string>("UnitL"),
r.Field<Decimal?>("OBFY"),
r.Field<Decimal?>("CFY")
})).GroupBy(g => g.Field<string>("Proc"));
It seems to me you are overusing DataRows. If you had your data in a nice class, you could write it like this:
data.GroupBy(x => x.Proc)
.Select(g => new
{
Proc = g.Key,
OBFYSum = g.Sum(x => x.OBFY),
CFYSum = g.Sum(x => x.CFY)
})
But if you really want to start with a DataTable and add the intermediate result to another DataTable, you could do it like this:
prodCostsTotals.AsQueryable()
.Select(r => dt.Rows.Add(new object[]
{
Convert.ToInt32(r.Field<string>("Proc")),
r.Field<string>("UnitL"),
r.Field<Decimal?>("OBFY"),
r.Field<Decimal?>("CFY")
}))
.GroupBy(g => g.Field<string>("Proc"))
.Select(g => new
{
Proc = g.Key,
OBFYSum = g.Sum(x => x.Field<Decimal?>("OBFY")),
CFYSum = g.Sum(x => x.Field<Decimal?>("CFY"))
})
Note that I have no idea whether your use of AsQueryable() will have any effect on the first part of this query, but it certainly won't have any effect on the grouping.