Contains statement in the LINQ queries - c#

I want do something like this:
string test = alarmType;
db.Alarms.Where(alarmType.Contains(m => m.Type)).ToList();
But this doesn't work. How can I make such query? Is it the only way to use pure SQL?
UPD
I'm trying to find whether records is substring of the "test", not conversly.

You have to reverse the condition:
var query = db.Alarms
.Where(a => alarmType.Contains(a.Type))
.ToList();
However, your code sample is confusing, if alarmType is a string i don't know what you're trying to achieve.
string test = alarmType;
Update: if you're using LINQ-To-Sql and you want to find all records where the Type is a substring of alarmType you can use:
var query = db.Alarms
.Where(a => SqlMethods.Like(alarmType, string.Format("%{0}%", a.Type)))
.ToList();

Try the following
string test = alarmType;
var result = db.Alarms.Where(m => alarmType.Contains(m.Type)).ToList();

Your LINQ query isn't well-formatted. You have:
db.Alarms.Where(alarmType.Contains(m => m.Type)).ToList();
So the parameter you've passed to Contains is a lambda, which isn't what Contains takes,
Likeiwse, Contains returns a bool, so you've passed a bool to Where, which is also not a parameter type it takes.
What you want is to pass a lambda to Where, like so:
db.Alarms.Where(m => alarmType.Contains(m.Type)).ToList();
Note how now both the Where and the Contains are being passed parameters of the correct type.

Related

Generate query expression from a string

I am trying to map a front end query builder to a backend ORM (OrmLite).
For instance, the front end might send 3 string values: SomeField, = foo.
If I want to generate this query in the ORM I would do:
var q = db.From<MyEntity>()
.Where(x => x.SomeField == "foo")
So what I need to do is come up with a way to build the where predicate from a string.
I can see the type Where is expecting is: Expression<Func<MyEntity,bool>>
So I think I need something like:
var q = db.From<MyEntity>()
.Where(GetQueryPart("SomeField", "=", "foo");
//....
public Expression<Func<T,bool>> GetQueryPart<T>(string field, string queryOperator, string value)
{
//...
}
But I am not exactly sure if this is the right approach or where exactly to start. I had a look through the docs here https://learn.microsoft.com/en-us/dotnet/api/system.linq.expressions.expression?view=net-5.0 and it is not clear to me how to build an expression.
Can someone give me some help with how I should approach this?

Select inside linq select

I have the following code (this is just relevant part):
linqQuery.Select(invoice =>
new InvoiceDetailed
{
UnpaidAmount = e.SumAmount +
e.OverdueNotices.OrderByDescending(on => on.SendDate).Select(on => on.Fee).DefaultIfEmpty(0).Sum() +
e.CreditNotes.Select(c => c.CreditNoteAmount).DefaultIfEmpty(0).Sum() -
e.Payments.Select(p => p.Amount).DefaultIfEmpty(0).Sum()
}
And this calculation for UnpaidAmount I repeat in severl other queries also. My question is if there is a way to somehow wrap that expression in function like:
Expression<Func<crmInvoice_Invoice, double>> unpaidExpression = // that unpaid amount caluculation expression
And then call like this:
linqQuery.Select(invoice =>
new InvoiceDetailed
{
UnpaidAmount = unpaidExpression(invoice)
}
Then I could reuse it in more queries. Is it possible to do something similar in LINQ? And if it is not is there any alternative solution u could suggest me to avoid repeating that part of code?
No, it's impossible.
Select method gets Expression as an argument. LINQ to SQL parses Expression to SQl code. So, to solve your task you need to convert you expression to return InvoiceDetailed:
Expression<Func<crmInvoice_Invoice, InvoiceDetailed>> InvoiceDetailedExpression = ...

Extracting lambda expression from LINQ

I have next chunk of code
var query = wordCollection.Select((word) => { return word.ToUpper(); })
.Where((word) =>
{
return String.IsNullOrEmpty(word);
})
.ToList();
Suppose I want to refactor this code and extract the lambda expression from Where clause. In Visual Studio I just select this lambda and do Refactor -> Extract Method. By doing so I have my LINQ modified to
var query = wordCollection.Select((word) => { return word.ToUpper(); })
.Where(NewMethod1())
.ToList();
and a NewMethod1() is declared as
private static Func<string, bool> NewMethod1()
{
return (word) =>
{
return String.IsNullOrEmpty(word);
};
}
The question is why this new method does NOT have any input parameters, as delegate Func states that NewMethod1() should have a string input parameter?
To get the expected result, mark just this part String.IsNullOrEmpty(word) and Extract the method:
private bool NewMethod(string word)
{
return String.IsNullOrEmpty(word);
}
What you originally got is because the extract created a method that returns a delegate. Not a method that matches the delegate. It is a method that returns another method. The latter accepts a string parameter word and returns a bool result.
Sure doing the above changes your code to:
.Where((word) => NewMethod(word))
But you can safely change that to:
.Where(NewMethod)
Side Note:
No need to use the return keyword in your Linq Queries or any one-line lambda, you can refactor you query to be like this:
var query = wordCollection.Select(word => word.ToUpper())
.Where(word => string.IsNullOrEmpty(word))
.ToList();
You are selecting the whole lambda, so it is trying to extract the whole lambda statement as a delegate that takes in a word and returns a boolean - Func < string, bool>.
When refactoring you should have only selected the "return String.IsNullOrEmpty(word);" part.
Additionally, you are using the lambas in an unnecessarily complex way.
You could refactor your LINQ statement to this:
var query = wordCollection.Select(word => word.ToUpper())
.Where(word => String.IsNullOrEmpty(word))
.ToList();
Or even to this:
var query = wordCollection.Select(word => word.ToUpper())
.Where(String.IsNullOrEmpty)
.ToList();

How to do "let" in dynamic LINQ?

How would I write this query in dynamic linq? I know how to do the select, but how do I do the "let"?
var qry = from sr in data.Addresses
let AddressType_Desc = sr.AddressType.AddressType_Desc
let Country_Desc = sr.Country.Country_Desc
where sr.Customer_GUID == CustomerGuid
select new
{
sr.Address_GUID,
sr.People_GUID,
sr.AddressType_GUID,
AddressType_Desc,
sr.Address1,
sr.Address2,
sr.City,
sr.State,
sr.Zip,
sr.County,
sr.Country_GUID,
Country_Desc,
sr.UseAsMailing
};
There is no equivalent of let in linq expression method syntax, as well in dynamic LINQ.
Let can only help you to make your queries more readable. It simply works as an alias or local variable. You can imagine, that in method syntax you won't be able to access it outside the scope of the method declared it.
In your case, just simply put the let variable initiation into the select.
Like this in linq method syntax:
var qry = data.Adresses.Where(sr => sr.Customer_GUID == CustomerGuid)
.Select(sr => new {
sr.Address_GUID,
....
sr.AddressType.AddressType_Desc,
sr.Country.Country_Desc
});
Or similar with dynamic LINQ (select clause as string):
var qry = data.Adresses.Where(sr => sr.Customer_GUID == CustomerGuid)
.Select("new (Address_GUID, AddressType.AddressType_Desc, Country.Country_Desc)");
And you will get the same result as with linq query syntax.
It would be similar for other expression methods. Only thing you need, is to use the value directly instead of the let alias.

LINQ OrderByDescending passing a string value

Hi I am trying to OrderByDescending() on a query but rather than:
results = results.OrderByDescending(o => o.Surname);
I wish to use:
results = results.OrderByDescending(o => "Surname");
The value in quotes would be passed in in a parameter.
I was looking at reflection but am unsure.
Have a look at LINQ Dynamic Query Library: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
this will allow you to use results.OrderByDescending("Surname");
I use something like this
results = results.OrderByDescending(o => o.GetType().GetProperty("Surname").GetValue(o, null).ToString())

Categories