I have a table of products and a table of categories, I can select by the ID of the Category like this:
var result = db.tblProducts.Where(p => p.tblCategories.Any(c => c.ID == 1));
However, I want to be able to select based on a list of Categories:
var catIDs = new List<int>() { 1,2,3 };
var results = db.tblProducts.Where(r => r.tblCategories.Any(t => catIDs.Contains(t.ID)));
I get the following error:
LINQ to Entities does not recognize the method 'Boolean Contains(Int32)' method, and this method cannot be translated into a store expression.
Presumably because I am using Contains to compare entities to local variables. Is there a way to do this?
Try create Expression from values. F.e.:
static Expression MakeOrExpression<T, P>(Expression<Func<T, P>> whatToCompare, IEnumerable<P> values)
{
Expression result = Expression.Constant(true);
foreach (var value in values)
{
var comparison = Expression.Equal(whatToCompare, Expression.Constant(value));
result = Expression.Or(result, comparison);
}
return result;
}
How to use:
var results = db.tblProducts.Where(r => r.tblCategories.Any(MakeOrExpression(t => t.ID, catIDs)));
The method MakeOrExpression will create an expression t.ID == 1 || t.ID == 2 || t.ID == 3 for list { 1, 2, 3 } dynamically, and then EF will translate it to SQL condition.
Maybe you can use this:
var catIDs = new List<int>() { 1,2,3 };
var results = db.tblCategories
.Where(t => catIDs.Contains(t.ID))
.SelectMany(t => t.tblProducts)
.Distinct();
Try this:
var query=from p in db.tblProducts
from c in p.tblCategories
where catIDs.Contains(c.ID)
select p;
If at least one of the categories of the product is in the catIDs list, then the product will be seleted.
Another option could be start by the categories (I'm guessing you have a many to many relationship between Product and Category and you have a collections of products in your Category entity):
var query=db.tblCategories.Where(c => catIDs.Contains(c.ID)).SelectMany(c=>c.tblProducts).Distinct();
Try this code :
var catIDs = new List<int>() { 1,2,3 };
var results = db.tblProducts.Where(r => catIDs.Any(c => c == r.tblCategories.Id));
Related
I'm trying to build a query selecting all records containing IDs which are stored in the list using that code:
var assistsIds = _context.Assistances.Where(c => c.IdUser == user.IdUser)
.Select(x => x.Owner.IdOwner).ToList();
Then I'm going through all the list elements to get a query:
var query = _context.Accounts.Where(_ => _.IsDeleted != 1);
foreach(var assist in assistsIds)
{
query = query.Where(_ => _.IdOwner == assist);
}
The result is that I'm getting something like this:
SELECT * FROM Accounts WHERE IdOwner = 1 AND IdOwner = 2 ...etc
Instead of:
SELECT * FROM Accounts WHERE IdOwner = 1 OR IdOwner = 2 ... etc
Is there a way to apply OR operator, or maybe there is some other way to achieve that?
You could use Contains:
var query = _context.Accounts
.Where(_ => _.IsDeleted != 1 && assistsIds.Contains(_.IdOwner));
This will return all records which match an Id in the assistsIds list.
How to change the following linq query to select another field value Field<int>("data_entry"),i want to select multiple fields .
var a = DF_Utilities.GetAvailableTasks(empnum, 1).AsEnumerable().Where(
p => p.Field<int>("task_code") == int.Parse(drpTasks.SelectedValue)).Select(p => p.Field<int>("cand_num")).First();
p.Field<int>("cand_num"),Field<int>("data_entry")
instead of p.Field<int>("cand_num")
You can use anonymous type:
var a = DF_Utilities.
GetAvailableTasks(empnum, 1).
AsEnumerable().
Where(p => p.Field<int>("task_code") == int.Parse(drpTasks.SelectedValue)).
Select(p => new
{
candNum = p.Field<int>("cand_num"),
dataEntry = p.Field<int>("data_entry")
}).
First();
I've this QueryOver where I select Log records where the Logs Name starts with D or F (using wildcards).
conv.InnerTransaction.Session.QueryOver<Log>()
.Where(l => l.DateTime > _datetime)
.And(
l => l.Name.IsLike("D%") || l.Name.IsLike("F%")
)
Instead I would like the name searching to be dynamically using values from a list. How can this be done?
I've tried something like:
var query = conv.InnerTransaction.Session.QueryOver<Log>()
.Where(l => l.DateTime > _datetime);
foreach (var name in _names)
{
query = query.And(l => l.Name.IsLike(name));
}
But that would result in multiple AND statements for each name in the list, whereas It just need to be a OR.
Have you tried Disjunction? I had a similar requirement once, but I had to use Conjunction instead. Disjunction will or multiple conditions together.
var disjunction = new Disjunction();
var query = Session.QueryOver<Log>().Where(l => l.DateTime > _datetime);
foreach (var name in _names)
{
disjunction.Add(Restrictions.On<Log>(log => log.Name).IsLike(name));
}
var queryResult = query.Where(disjunction).List<Log>();
I am currently using Linq to retrieve a list of distinct values from my data table. I am then looping through the list and again calling a linq query to retrieve a list of values for each
value in the first list.
_keyList = new SortedList<int, List<int>>();
var AUGroupList = ProcessSummaryData.AsEnumerable()
.Select(x => x.Field<int>("AUGroupID"))
.Distinct()
.ToList<int>();
foreach (var au in AUGroupList)
{
var AUList = ProcessSummaryData.AsEnumerable()
.Where(x => x.Field<int>("AUGroupID") == au)
.Select(x => x.Field<int>("ActivityUnitID"))
.ToList<int>();
_keyList.Add(au, AUList);
}
I am then adding the value to a sorted list along with the corresponding second list.
How can I combine the above two queries into one Linq query so that I don't have to call them separately?
You should be able to do something like:
var groupQuery = from d in ProcessSummary.AsEnumerable()
group d by new { Key = d.Field<int>("AUGroupID") } into g
select new { GroupID = g.Key, Values = g.Distinct().ToList() };
Then you can loop through the groupQuery and populate the sorted list. The Key property will contain the group id, and the Values property will have a distinct list of values.
Have you tried this?
var _keyList = new SortedList<int, List<int>>();
var AUGroupList = ProcessSummaryData.AsEnumerable()
.Select(x => x.Field<int>("AUGroupID"))
.Distinct()
.Where(x => x.Field<int>("AUGroupID") == au)
.Select(x => x.Field<int>("ActivityUnitID"))
.ToList<int>();
_keyList.Add(au, AUList);
}
Your provider should cope with that, if not there's a few other ways.
Say I have a list of EF entity names like:
List<string> entityNames = new List<string>(){
"Table1",
"Table2",
"Table3"
};
From this list of entities I want to query each entity individually, similar to:
var result = efContext.Table1.Where(t => ...);
Using reflection, or black magic, how would I obtain a reference to the actual entity so that I could wind up with something like:
foreach(var e in entityNames)
{
var entity = efcontext.GetType().GetProperties().Where(t => t.Name == e).Single();
var result = efContext.entity.Where(t => ...);
}
Thoughts?
Supposing that all of the Entity types listed implement some common interface that you intend to use in your Where clause, you could do something like this:
foreach(var e in entityNames)
{
PropertyInfo entityProperty = efcontext.GetType().GetProperties().Where(t => t.Name == e).Single();
var baseQuery = (IQueryable<IMyEntity>)entity.GetValue(efContext, null);
var result = baseQuery.Where(t => ...);
}