QueryOver: Dynamically adding IsLike in Where clause - c#

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>();

Related

How can I get build a query based on array of IDs using EF

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.

Select by ID from a list

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));

How to select multiple fields (LINQ)

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();

"OR" on-demand with Linq to Entities, how can i do it?

I have the following query that performs a "AND" on-demand:
var products = // Selecting a list of products in anywhere based in a filter...
foreach (var product in products)
{
query = query.Where(p => p.Code == product.Code); // with this way, this query make no sense because this happens in any scenario, never a code can be more than one code.
}
So, how can i do the same query but performing a "OR" on-demand (so that the query makes sense)?
You can use the facsimile of an IN for LINQ:
var productCodeList = products.Select(p => p.Code).ToList();
query = query.Where(p => productCodeList.Contains(p.Code));
It's basically saying:
SELECT *
FROM products
WHERE code IN (<list_of_codes>)
Using Contains:
var codes = products.Select(x => x.Code).ToArray();
query.Where(p => codes.Contains(p.Code));
Either use the Contains method ad Brad and Joe wrote, or (when that's not possible) use the PredicateBuilder:
var predicate = PredicateBuilder.False<Product>();
foreach (var product in products)
{
var code = product.Code;
predicate = predicate.Or(p => p.Code == code);
}
var products dataContext.Products.Where(predicate);

Filter a LINQ query

Here's my query.
var query = from g in dc.Group
join gm in dc.GroupMembers on g.ID equals gm.GroupID
where gm.UserID == UserID
select new {
id = g.ID,
name = g.Name,
pools = (from pool in g.Pool
// more stuff to populate pools
So I have to perform some filtering, but when I attempt to filter
var filter = query.Where(f => f.pools.[no access to list of columns]
I can't access any of the items within "pools". Does anyone know how I'm able to access that?
What I'd like to do is this:
var filterbyGame = query.Where(f = > f.pools.GameName == "TestGame");
Let me know if that's even possible with thew ay I have this setup.
Thanks guys.
In your query you can't do Where(f => f.pools.GameName)
because f is an IEnumerable<>
Something like this should work:
Where(f => f.pools.Any(p => p.GameName == "TestGame"))
pools is an enumeration, not a single instance. That's why you're not getting column names.
You need to change your filter to something like:
var filterByGame = query.Where(f => f.pools.Any(p => p.GameName == "TestGame"));

Categories