I am trying to do something similar to my previous post, except I am using extension methods instead of LINQ. I get an error telling me that && cannot be used, so how would I search within a table using two strings entered by the user?
var query = (App.DBConnection.Table<Notes>().Where(
c => c.Note.Contains(textBox1.Text) && c => c.Note.Contains(textBox2.Text))).Single();
TextBox_Results.Text = query.Note;
Remove the second lambda operator c =>
var query = App.DBConnection.Table<Notes>()
.Where(c => c.Note.Contains(textBox1.Text)
&& c.Note.Contains(textBox2.Text)))
.Single();
Apart from that, i would use FirstOrDefault instead of Single. The latter throws an InvalidOperationException if there are no elements or if there are more than one. The former just returns null if no item matches the predicate in the Where.
You don't need to declare the c variable again
Where(c => c.Note.Contains(textBox1.Text) && c => c.Note.Contains(textBox2.Text)))
should be
Where(c => c.Note.Contains(textBox1.Text) && c.Note.Contains(textBox2.Text)))
Related
I need to set a variable's value to the value of a property that is nested in several Lists. Each list only has one item except for one list. I'm trying to do this:
var myValue = myListA[0].myListB[0].myListC[0].
myListD.Where(x => x.Name == "Misc Expenses").myListE[0].price;
This produces a compile time error that says myListD does not contain a definition for myListE. What is the correct syntax?
After the .Where clause, you need to to .First() (or .ToList()) in order to apply the Where clause:
var myValue = myListA[0].myListB[0].myListC[0].
myListD.Where(x => x.Name == "Misc Expenses").First().myListE[0].price;
Technically, though, you can replace that .Where with .First directly, too:
var myValue = myListA[0].myListB[0].myListC[0].
myListD.First(x => x.Name == "Misc Expenses").myListE[0].price;
I am trying to simplify a method that returns an IQueryable
A, B and C extend BaseEntity containing a enum that I want to compare.
context is a entity framework dbcontext.
Here is a stripped down version of the method:
return context.MyEntities.Include("A").Include("B").Include("C")
.Where(x => x.A.MyEnum == MyEnum.<value> && x.B.MyEnum == MyEnum.<value> && x.C.MyEnum == MyEnum.<value>);
I tried to do this:
Func<BaseEntity, bool> equals = x => x.MyEnum == MyEnum.<value>;
return context.MyEntities.Include("A").Include("B").Include("C")
.Where(x => equals(x.A) && equals(x.B) && equals(x.C));
It compiles but gives a runtime error. For what I understand is that Linq cannot translate the func<> to SQL?
So i searched and I found that you need to wrap the func<> in an expression<>, so Linq can compile it and translate it to SQL.
Now I have this:
Expression<Func<BaseEntity, bool>> equals = x => x.MyEnum == MyEnum.<value>;
return context.MyEntities.Include("A").Include("B").Include("C")
.Where(x => equals(x.A) && equals(x.B) && equals(x.C));
But this doesn't compile: 'Method name expected'.
Is there a way to accomplish what i'm trying to do?
The compile error is because you have to first compile the expression before being able to invoke it.
equals.Compile()(x.A)
But this defeats the purpose of using the expression to begin with.
There is nothing to be simplified in the provided code other than moving the repeated value call into a variable.
var value = MyEnum.<value>;
return context.MyEntities.Include("A").Include("B").Include("C")
.Where(x => x.A.MyEnum == value && x.B.MyEnum == value && x.C.MyEnum == value);
The attempt to simplify what was shown is not really needed.
I want to use OR function in my linq query.
Ex:
Sql:
select * from tblusers where userid=1 and status='a' or status='b';
Linq:
var result= _Repository.selectAll().where(x=>x.UserID==1 && x.status=="a" OR x.status=="B");
It's does work for linq query. so does anyone have any idea?
So you are aware about the && operator for comparison, then why not make a try with || operator? Anyway here is the solution for your problem, Following code will get you the result with UserID is 1 and status is either a or B.
_Repository.selectAll().where(x=>x.UserID==1 && (x.status=="a" || x.status=="B"));
Create an array of status you want to check and then use contains. something like this.
var statusList = new[] {"a", "b"};
.Where(x=> x.UserID == 1 && statusList.Contains(x.status));
Adding my 2 cents in here, there is another way you can write your sql query in C# which more or less resembles the sql syntax.
var result = from x in _Repository.SelectAll() where x.UserID == 1 && (x.Status == "a" || x.Status == "B") select x;
This syntax is Query Syntax/Expression where as your snippet is Method Syntax/Expression. Both will achieve same results. Also behind the scene, query syntax is compiled to Method syntax.
At compile time, query expressions are converted to Standard Query Operator method calls according to the rules set forth in the C# specification. Any query that can be expressed by using query syntax can also be expressed by using method syntax. However, in most cases query syntax is more readable and concise.
Or other approach with List.Contains, which generates sql query like
SELECT * FROM tblusers WHERE userid=1 AND status IN ('a','b');
var acceptedStatus = new List<string> { 'a', 'b' };
var result= _Repository.selectAll()
.Where(x => x.UserID == 1)
.Where(x => acceptedStatus.Contains(x.Status));
Notice that instead of && operator you can use another Where function and chain them. Can be more readable then fit all conditions in one line.
Try code:
var result =( from x in _Repository.selectAll()
where x.UserID==1 && (x.status=="a" || x.status=="B") select x);
another Solution
var result =( from x in _Repository.selectAll().where(c=>c.status=="a" || x.status=="B")
where x.UserID==1 select x);
How to set multiple values of a list object, i am doing following but fails.
objFreecusatomization
.AllCustomizationButtonList
.Where(p => p.CategoryID == btnObj.CategoryID && p.IsSelected == true && p.ID == btnObj.ID)
.ToList()
.ForEach(x => x.BtnColor = Color.Red.ToString(), );
In the end after comma i want to set another value.
What should be the expression, although i have only one record relevant.
Well personally I wouldn't write the code that way anyway - but you can just use a statement lambda:
A statement lambda resembles an expression lambda except that the statement(s) is enclosed in braces
The body of a statement lambda can consist of any number of statements; however, in practice there are typically no more than two or three.
So the ForEach call would look like this:
.ForEach(x => {
x.BtnColor = Color.Red.ToString();
x.OtherColor = Color.Blue.ToString();
});
I would write a foreach loop instead though:
var itemsToChange = objFreecusatomization.AllCustomizationButtonList
.Where(p => p.CategoryID == btnObj.CategoryID
&& p.IsSelected
&& p.ID == btnObj.ID);
foreach (var item in itemsToChange)
{
item.BtnColor = Color.Red.ToString();
item.OtherColor = Color.Blue.ToString();
}
(You can inline the query into the foreach statement itself, but personally I find the above approach using a separate local variable clearer.)
I have an entity framework object called batch, this object has a 1 to many relationship to items.
so 1 batch has many items. and each item has many issues.
I want to filter the for batch items that have a certain issue code (x.code == issueNo).
I have written the following but Im getting this error:
items = batch.Select(b => b.Items
.Where(i => i.ItemOrganisations
.Select(o => o
.Issues.Select(x => x.Code == issueNo))));
Error 1:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<bool>>' to 'bool'
Error 2:
Cannot convert lambda expression to delegate type 'System.Func<Ebiquity.Reputation.Neptune.Model.Item,bool>' because some of the return types in the block are not implicitly convertible to the delegate return type
Select extension method needs a lambda expression that returns a boolean, but the inner o.Issues.Select returns an IEnumerable of boolean to the outer Select(o => o which result in the exception you're getting.
Try using Any instead which verifies that at least one element verifies the condition:
items = batch.Select(
b => b.Items.Where(
i => i.ItemOrganisations.Any(
o => o.Issues.Any(x => x.Code == issueNo)
)
)
);
If I understand correctly, you're trying to select through multiple layers of enumerables. In those cases you need SelectMany which flattens out the layers, not Select. LINQ's syntax sugar is made specifically to make SelectMany easier to reason about:
var items = from item in batch.Items
from org in item.ItemOrganizations
from issue in org.Issues
where issue.Code == issueNo
select item;
The compiler translates that into something like this:
var items = batch.Items
.SelectMany(item => item.ItemOrganizations, (item, org) => new {item, org})
.SelectMany(#t => #t.org.Issues, (#t, issue) => new {#t, issue})
.Where(#t => #t.issue.Code == issueNo)
.Select(#t => #t.#t.item);
You can always wrap this in a Distinct if you need to avoid duplicate items:
var items = (from item in batch.Items
from org in item.ItemOrganizations
from issue in org.Issues
where issue.Code == issueNo
select item).Distinct();
It's hard to tell what you're trying to do based on your code but I think you're looking for something like this;
var issue = batch.Select(b => b.Items).Select(i => i.Issues).Where(x => x.Code == issueNo).Select(x => x).FirstOrDefault();
The above query will return the first issue where the Issues Code property is equal to issueNo. If no such issue exists it will return null.
One problem (the cause of your first error) in your query is that you're using select like it's a where clause at the end of your query. Select is used to project an argument, when you do Select(x => x.Code == issueNo) what you're doing is projecting x.Code to a bool, the value returned by that select is the result of x.Code == issueNo, it seems like you want that condition in a where clause and then you want to return the issue which satisfies it which is what my query is doing.
items = from b in batch.Include("Items")
where b.Items.Any(x=>x.Code==issueNo)
select b;
You're getting lost in lambdas. Your LINQ chains are all embedded in each other, making it harder to reason about. I'd recommend some helper functions here:
static bool HasIssueWithCode(this ItemOrganization org, int issueNo)
{
return org.Issues.Any(issue => issue.Code == issueNo);
}
static bool HasIssueWithCode(this Item items, int issueNo)
{
return items.ItemOrganizations.Any(org => org.HasIssueWithCode(issueNo));
}
Then your answer is simply and obviously
var items = batch.Items.Where(item => item.HasIssueWithCode(issueNo));
If you inline these functions, the result is the exact same as manji's (so give manji credit for the correct answer), but I think it's a bit easier to read.