use "Like" Expression, LINQ to Entity - c#

I spent long time trying to fix this but I'm not getting anywhere, so i help someone helps me.
I have a search form where I wish to use the Like % operator in the textbox.
Here is a snippet of my code:
var data = mg.DatabaseTable.Where(m => m.UserName.StartsWith(TextBoxUserID.Text) &&
m.Content.Like(%TextBoxBarcode.Text&) &&
m.Action.StartsWith(DropDownListStatus.Text) &&
m.Site.Contains(TextBoxSite.Text));
I would like it to be possible to use "%%" in the m.Content(textbox) or however it's made.
I am aware the use of StartsWith, EndWith and Contains. I would like to make it possible to choose how to query the search by using "like %"

You can use:
m.Content.StartsWith(TextBoxBarcode.Text);
for
like 'search%'
or:
m.Content.EndsWith(TextBoxBarcode.Text);
for
like '%search'
or:
m.Content.Contains(TextBoxBarcode.Text);
for
like '%search%'
If you want the user to be able to choose the type of search then you'll need to have a switch and then three different queries. Either replicate the query or perform the basic query once and then filter the results of that depending on the switch:
var data = mg.DatabaseTable.Where(m => m.UserName.StartsWith(TextBoxUserID.Text) &&
m.Action.StartsWith(DropDownListStatus.Text) &&
m.Site.Contains(TextBoxSite.Text));
if (searchMode == StartsWith)
{
return data.Where(m => m.Content.StartsWith(TextBoxBarcode.Text);
}
else if (searchMode == EndsWith)
{
return data.Where(m => m.Content.EndsWith(TextBoxBarcode.Text);
}
else
{
return data.Where(m => m.Content.Contains(TextBoxBarcode.Text);
}

Related

How to use if statement within IMongoCollection.Find() method?

I have two different filter options for the Find() method depending on the value of the parameter. So I want to combine them in one lambda function.
It is easy to write separate methods for each options:
if (status == null)
{
var dbOrders = orderCollection
.Find(t => true)
.ToList();
}
else
{
var dbOrders = orderCollection
.Find(t => t.Status==status)
.ToList();
}
Obviously, it is not the best way to do. I think it can be done within one lambda function.
I have tried something like that, but it seems that it is not correct
var dbOrders = orderCollection
.Find(t => status == null: true ? t.Status==status)
.ToList();
What is the correct way to achieve it?

LINQ Query, Return Max Value with Where Clause

I'm working on an API; how can I set my linq query up to return the max value with a where condition?
See the example code below; I can return the max value of the field I want, but I need to filter it where another column value equals something.
var lot = db.ShrinkLotData.Where(x => x.SupplierMfgLot.ToLower() == label.SupplierMfgLot.ToLower() && x.CatPattern.ToLower() == label.CatPattern.ToLower())
.SingleOrDefaultAsync();
if (lot.Result == null)
{
var lots = db.ShrinkLotData.Where(x => x.CatPattern.ToLower() == label.CatPattern.ToLower());
int internallot = db.ShrinkLotData.Max(x => x.InternalLotNum).Value;
return Ok(lot);
}
return Ok(lot);
}
for the internallot, I want to return the highest value using similar syntax as the lots syntax.. (Where the catpattern equals a specific value)
What am I overlooking?
Thanks!
If I understand correctly, you basically need to use Where and Max together, so that you can select max value with a where condition.
db.ShrinkLotData.Where(x => x.CatPattern.ToLower() == label.CatPattern.ToLower()).Max(x => x.InternalLotNum).Value;
More Info : Composability of Queries:
..., you compose them in method syntax by
chaining the method calls together. This is what the compiler does
behind the scenes when you write queries by using query syntax. And
because a query variable does not store the results of the query, you
can modify it or use it as the basis for a new query at any time, even
after it has been executed.

Indexing IQueryable<int>?

How do you index an IQueryable?
I am using a LINQ to sql query to get in values from a particular column. The query is as follows,
var intitalQuery = (from a in sql.GetTable<Staff_Time_TBL>()
where a.Info_Data == SelectedOption
select a.Staff_No).Distinct();
From there I want to be able index the intitalQuery variable and get values as needed.
That value is then used in another query.
My first try was this,
Column1.DataContext = sql.Staff_Time_TBLs.Where(item =>
item.Section_Data == SelectedOption &&
item.Staff_No == intitalQuery[0];
Then I tried this from here with no luck.
Column1.DataContext = sql.Staff_Time_TBLs.Where(item =>
item.Section_Data == SelectedOption &&
item.Staff_No == intitalQuery.First());
From what I can from the link is that that way gets just the first value, I want to be able to get all values via indexing. How do you go about that?
IQueryable<T> inherits from IEnumerable and as such has a wealth of extension methods to accomplish almost anything you'd need from a sequence. In particular, .ToList() turns an enumerable into a List<T> that allows efficient indexing.
.ToList() is slightly more efficient than the more obvious .ToArray() when working with sequences of unknown initial length, because .ToArray() requires an additional copy to end up with an array of exactly the right size. (But arrays are faster to loop over, so it all depends on what you're doing.)
You can do this:
public static List<Staff_Time_TBLs> GetIndexed(string staffNo){
var stuff = sql.Staff_Time_TBLs.Where(item =>
item.Section_Data == SelectedOption &&
item.Staff_No == staffNo;
return stuff.ToList();
}
//to use it...
initialQuery.ForEach(p=>{
var indexvalue = GetIndexed(p)
});

How to use System.Linq.Expressions.Expression to filter based on children?

I have a filter that I use across many methods:
Expression<Func<Child, bool>> filter = child => child.Status == 1;
(actually is more complex than that)
And I have to do the following
return db.Parents.Where(parent => parent.Status == 1 &&
parent.Child.Status == 1);
where the condition is the same as in the filter above.
I want to reuse the filter in this method. But I don't know how. I tried
return db.Parents.Where(parent => parent.Status == 1 &&
filter(parent.Child));
but an Expression can't be used as a method
If you want to combine expressions and still be able to use linq-to-sql, you may want to have a look at LinqKit. It walks inside your expression and replaces all the function calls by their contents before the sql conversion.
This way you'll be able to use directly
return db.Parents
.AsExpandable()
.Where(parent => parent.Status == 1 && filter(parent.Child));
You can try this:
var compiledFilter = filter.Compile();
foreach (var parent in db.Parents.Where(parent => parent.Status == 1))
if (compiledFilter(parent.Child))
yield return parent;
It requires you to pull all of the parents, but unlike #HugoRune's solution, it doesn't require a 1:1 relation of Parent:Child.
I don't think this will be useful for your situation because of the different types involved, but just in case, here is an example of how you can combine Expressions: How do I combine LINQ expressions into one?
Edit: I had previously suggested using Compile(), but that doesn't work over LINQ-to-SQL.
Well, if there is a 1:1 relationship between parent and child
(unlikely, but the example seems to imply that) then you could do it like this:
return db.Parents
.Where(parent => parent.Status == 1)
.Select(parent => parent.Child)
.Where(filter)
.Select(child=> child.Parent);
Otherwise it will be hard.
You could do it with dynamic linq but that is probably overkill.
You could generate your expression tree manually, but that is also quite complicated. I have not tried that myself.
As a last resort you could of course always call yourQuery.AsEnumerable(), this will cause linq-to-sql to translate your query into sql up to this point and perform the rest of the work on the client-side; then you can .compile() your expression. However you lose the performance benefits of linq-to-sql (and compile() itself is quite slow; whenever it is executed, it calls the JIT-compiler):
return db.Parents
.Where(parent => parent.Status == 1)
.AsEnumerable()
.Where(parent => filter.Compile().Invoke(parent.Child))
Personally I'd just define the expression twice, once for child and once for parent.child:
Expression<Func<Child, bool>> filterChild = child => child.Status == 1;
Expression<Func<Parent, bool>> filterParent = parent => parent.Child.Status == 1;
Might not be the most elegant, but probably easier to maintain than the other solutions
Just come up with this, check if this would work for you
public interface IStatus { public int Status { get; set; } }
public class Child : IStatus { }
public class Parent : IStatus
{public Child Child { get; set; } }
Func<IStatus, bool> filter = (x) => x.Status == 1;
var list = Parents.Where(parent => filter(parent) && filter(parent.Child));
Hope this helps!
Could you just use the expression as a function instead?
Instead of:
Expression<Func<Child, bool>> filter = child => child.Status == 1;
Use that same expression as a generic function this way:
Func<Child, bool> filter = child => child.Status == 1;
Then you will be able to use the function in just the same way you were trying to use an expression:
return db.Parents.Where(parent => parent.Status == 1 &&
filter(parent.Child));
Edit: I misunderstood the question. This is a bad answer. 6+ years out, I'm still getting comments to the effect that this doesn't work. I'm not sure, from a hygiene perspective, if it would be better to just delete the answer, or add this edit and let the answer stand as an example of something that decidedly doesn't work. I'm open to advisement on that.
There's no need for external libraries or mucking around with expression trees. Instead, write your lambda functions to use query chaining and take advantage of LINQ's deferred execution.
Instead of:
Expression<Func<Child, bool>> filter = child => child.Status == 1;
Rewrite it as:
Func<IQueryable<Parent>, IQueryable<Parent>> applyFilterOnParent = query => query.Where(parent => parent.Child.Status == 1);
Func<IQueryable<Child>, IQueryable<Child>> applyFilterOnChild = query => query.Where(child => child.Status == 1);
Now, instead of:
return db.Parents.Where(parent => parent.Status == 1 &&
filter(parent.Child));
You can write:
var query = db.Parents.AsQueryable();
query = applyFilterOnParent(query);
return query.Where(parent => parent.Status == 1);
And you can re-use the applyFilter functions in other LINQ queries. This technique works well when you want to use lambda functions together with LINQ-to-SQL, because LINQ will not translate a lambda function to SQL.

Possible to do this in linq?

I am wondering if something like this could be done(of course what I have written does not work but that's what I am essentially trying to achieve) .
var test = u.Owner;
a.Table.Where(u => test == true)
I have a linq query that I want to reuse(basically I got a query that I use 5 times) and the only thing that changes is what I am comparing against.
So in the above u.Owner is compared against true. In another query it would look the same but instead of u.Owner I might have u.Add == true or u.Edd == true.
So is there a way I can sort of reuse what I have. Of course in my code the query is a bit longer but I just shortened down.
Edit
Basically the whole query
List<Permission> clearence = user.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner)).ToList();
permissionNeeded == Enum
So my orignal way of doing it was u.Permission.Name == permissionNeeded so I compared the enum value to a string.
Now my db model has change and I need to check against 5 different permissions separately that are bools and not strings.
u.Add = true || u.Owner == true;
u.Edit = true || u.Owner == true;
u.Delete= true || u.Owner == true;
u.View= true || u.Owner == true;
Thats all changes for the entire query so that's why I am trying to make it into one query(just like I had it before).
So I am thinking of having a switch statement. The method still takes in a permissionNeeded(enum) I then go through and determine what clause I need and some how insert it into the query.
switch(PermssionNeeded)
{
case PermissionTypes.Add:
u.Add;
break;
// all other cases here.
}
Take advantage of the fact that Where can have any function taking type Table as a parameter and returning a boolean to create a function like:
public IQueryable<Table> QueryTables(Func<Table, bool> testFunction)
{
return a.Table.Where(testFunction).AsQueryable<Table>();
}
Edit: (in addition to edit to add AsQueryable above, which I earlier forgot)
If all you want to do is vary the boolean field used in the test, and you don't want to have to specify an entire function (which you're about to find out is much easier), you would need to use some reflection:
using System.Reflection;
public IQueryable<Table> QueryTables(PropertyInfo pi)
{
return a.Table.Where(t => (bool)(pi.GetGetMethod().Invoke(t, null))).AsQueryable<Table>();
}
To construct the PropertyInfo object, use something like:
PropertyInfo pi = typeof(Table).GetProperty("Owner");
I prefer the earlier method, but I did want to show that something like this is at least possible.
If you only want to specify the property you are checking you can do
public IEnumerable<Table> GetTables(Func<Table,bool> getValue)
{
return a.Table.Where(table => /*some common filter*/)
.Where(table => getValue(table))
}
var query = from u in uSrc join v in vSrc on u.ID equals v.RelatedUID
where v.Valid && u.Created < DateTime.UtcNow.AddDays(-365)
select u; // relatively complicated starting point.
var q1 = query.Where(u => u.Add); // must also have Add true
var q2 = query.Where(u => u.Test); // must also have Test true
var q3 = query.Where(u => u.ID < 50); // must also have ID < 50
And so on.
Edit:
Okay, so your starting query is:
List<Permission> clearence = student.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner)).ToList();
However, note that this creates a list, so any further work done on it will be a matter of Linq-to-objects. We'll come back to that in a minute, as it's sometimes good and sometimes not.
Now, if I understand you correctly, you need different sets for different cases, which you can do with your query as per:
var set0 = clearance.Where(u.Add = true || u.Owner == true);
var set1 = clearance.Where(u.Edit = true || u.Owner == true);
var set2 = clearance.Where(u.Delete= true || u.Owner == true);
var set3 = clearance.Where(u.View= true || u.Owner == true);
Now, this will work, but may not be the best approach. If we go back to the original query, we don't have to do ToList(), but can have:
IQueryable<Permission> clearence = student.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner));
Now, in the first case because we built a list we first got all values that matched the critera backed, and then stored it in memory, in clearance.
In the second case, clearance doesn't store any values at all, but instructions on how to get them.
The question is which is better to use. In the case where we are going to end up using the vast majority of the objects returned by the first query on its own, then there is a performance boost in using the list version, because they are loaded into memory only once, and then taken from memory without hitting the database again.
However, in most cases, it's better to do the second version for two reasons:
We hit the database in each case, but only retrieve the objects needed in that case.
We don't store anything in memory longer than necessary. Above a certain amount this is an important performance matter in itself.
The time to first item is faster this way.
We can further refine, for example if we do the following:
var trimmed = from set0 select new{u.Id, u.Permission.Name};
The we retrieve anonymous objects with Id and Name properties that are all we care about for a particular case, and not all of the relevant fields are retrieved from the database, or other source.
I've recently come to prefer a Dictionary over switch statements. You could store all your lambas in a Dictionary<PermissionNeeded, Func<User, bool>> that would look like this:
Dictionary<PermissionNeeded, Func<User, bool>> Permissions =
new Dictionary<PermissionNeeded, Func<User, bool>> {
{ PermissionNeeded.Add, u => u.Add }, // don't need to specify == true
{ PermissionNeeded.Edit, u => u.Edit },
...
etc
};
And you would call it like this:
var clearance = Permissions[PermissionNeeded.Add](user);
or maybe
var clearance = Permissions[PermissionNeeded.Add](user) && Permissions[PermissionNeeded.Edit](user);
or perhaps
var clearance = Permission[PermissionNeeded.Add](user) || Permissions[PermissionNeeded.View](user);
and so on. Even if you don't have a user object, I think this would still be valid and make the code pretty easy to read, and if you have to modify your functions, its all in the dictionary...

Categories