How to parameterize a boolean expression in Linq? - asp.net-mvc

I have a Linq statement that looks something like:
Report.Where(a=>a.Property == 1 || a.Property == 2 || a.Property == 3).Count()
I would like to know if I can refactor the statement into something of the form:
Report.Where(a=a.Property == validProperties)
where I can store a set of validProperties as an array of integers.

You can use Contains method
var idsToCheck = new List<int> {1,2,3};
var someCount = Report.Where(a=>idsToCheck.Contains(a.Property)).Count();
Or call the Count first and pass the lambda expression to that.
var someCount = Report.Count(a => idsToCheck.Contains(a.Property));

Related

Foreach using list inside the lambda syntax to perform multiple where clause

I want to perform a multiple where clause using foreach statement inside lambda list expression. It is possible to do that? Please help me. Thanks. Here's my code:
//The cat values are "Toys,Accessories,Shirts"
var listCategories = cat.Split(',').ToList();
var GetProd = db.vwProducts.Where(x => foreach(var category in listCategories) { x.CategoryName.ToLower().Contains(category) && } x.Status == 1).ToList();
I already solved my question. You do not use the foreach to loop through list.I use the List statement to loop over the query. Here's my code.
//cat values "Toy,Shirt,Accessories"
List<string> categories = cat.Split(',').ToList();
var GetProd = db.vwProducts.Where(x => categories.Contains(x.CategoryName) && x.Status == 1).OrderBy(x => x.Name).ToList();

More concise LINQ with 'or' clause

I have a small LINQ query containing a Where clause; something like:
var blueRedGreenBikes = GetBikes(filter)
.Where(a => a.Color == "Blue" || a.Color == "Red" || a.Color == "Green")
.Count()
I am looking for a way to write this type of query more concisely using LINQ. In SQL, I might write a similar WHERE clause like:
WHERE bike.Color IN ('Red','Blue','Green')
You can use the LINQ Contains method to check your item's color against a collection.
var colorList=new List<string> { "Blue","Red","Green"};
var blueRedGreenBikes = GetBikes(filter).Where(a => colorList.Contains(a.Color)).Count();
Another version
var blueRedGreenBikes = GetBikes(filter).Count(s => colorList.Contains(s.Color));

LINQ Union Allways returning empty sets

I'm doing some LINQ to look for keywords typed in a textbox. Each keyword ends with ";" and i need to look for itens that contain at least one of those keys.
I thought that i would be able to achieve this with this loop
IEnumerable<ItemFAQ> allResults = null;
foreach (var item in termosPesquisaIsolados)
{
IEnumerable<ItemFAQ> tempResults =
_dbHelpDesk.ItemFAQ
.Where(x => x.DescricaoResposta.Contains(item) || x.TituloTopico.Contains(item))
.ToList()
.Select(x => new ItemFAQ
{
IdPergunta = x.IdPergunta,
TituloTopico = x.TituloTopico,
DescricaoResposta = x.DescricaoResposta.Substring(0, 100)
});
if (allResults != null)
allResults = allResults.Union(tempResults);
else
allResults = tempResults;
}
At first iteration tempResult returns in a test 3 elements then it passes then to allResult, everything ok with that.
The second iteration, tempResult returns 2 ocurrences... then according to code allResult should receive the Union of AllResult and the TempResults, but no matter what i do, when i use the Union clause the result in an Empty Set.
So 3 + 2 = 0 at the end after using Union.
Do you guys can see the mistake at this peace of code or know some issues that could lead to this error ?
Thanks for your time.
try replacing this line:
allResults = allResults.Union(tempResults);
with:
allResults = allResults.Union(tempResults).ToList();

How to specify a condition in an Entity Framework join?

I have a Blogs table related to BlogComments table with a FK.
I need to get, through Linq, all the BlogComments items that match a certain flag
If i do:
db.Blogs.Where(b => b.BlogComments.Where(bc=>bc.Where(bc.Flag1==true));
I get "Cannot implicity convert type IEnumerable to bool"
Which is the best way to solve this problem?
Because this expression:
b.BlogComments.Where(...)
returns an IEnumerable (of BlogComments), but you are then passing it into this method:
db.Blogs.Where(...)
which expects a function that returns a bool, not an IEnumerable.
You probably need something like this:
var blogId = 5;
db.BlogComments.Where(bc => bc.BlogId == blogId && bc.Flag1 == true)
If you need to select comments from multiple blogs, then you could try using Contains:
var blogIds = new [] {1,2,3,4,5};
db.BlogComments.Where(bc => blogIds.Contains(bc.BlogId) && bc.Flag1 == true)
If you want to place criteria on the set of blogs, as well as the comments, then you could do this in one query using a join:
var query = from b in db.Blogs
join c in db.BlogComments on c.Blog equals b
where b.SomeField == "some value"
&& c.Flag1 == true
select c;
You could write it in LINQ form.
var blogs = from b in db.Blogs
join c in db.BlogComments
on b.BlogId equals c.BlogId
where c.Flag1
select b;
If you have a composite key you can write
on new { A = b.BlogKey1, B = b.BlogKey2 }
equals new { A = c.CommentKey1, B = c.CommentKey2 }
If it were me, I would just have another DbSet in your DbContext.
DbSet<BlogComment> BlogComments
and just search through there without going through Blogs.
db.BlogComments.Where(bc => bc.Flag1 == true);
If anyone knows if there's anything wrong in doing so, then I'm all ears :)

how can I use FirstOrDefault()?

I have this code and I want to set a value to Viewdate when the expression returns no data:
ViewData["Fix"] = db.PreStatusViws.Where(c => c.LkpNameFix == "1").FirstOrDefault().NumCoefficientFix;
can I set zero or a "Text" for that? I no, what can I do?!
note: FirstOrDefault(null) cause an error.
If I understand your question correctly, the following code should solve your problem:
var p = db.PreStatusViws.Where(c => c.LkpNameFix == "1").FirstOrDefault();
if(p != null)
ViewData["Fix"] = p.NumCoefficientFix;
else
ViewData["Fix"] = 0;
Default will return the default for the data type. If the data type in that place is a reference type (e.g. string) the default value will always be null, and therefore the following .NumsCoefficientFix member will throw a NullReferenceException.
The default value is built into .NET and not changeable, and is always given if the result set contains no value.
#Mikey has already given the code sample in his answer that I would suggest.
If you first select the numeric column, FirstOrDefault will work as you intend, returning either a value or 0 (the default for numeric types):
ViewData["Fix"] = db.PreStatus
.Select (c => c.NumCoefficientFix)
.FirstOrDefault (c => c.LkpNameFox == "1");
If NumCoefficientFix is a nullable type, then use the ?? operator to convert the null into 0:
ViewData["Fix"] = db.PreStatus
.Select (c => c.NumCoefficientFix)
.FirstOrDefault (c => c.LkpNameFox == "1") ?? 0;
Selecting the NumCoefficientFix first is also (slightly) more efficient for LINQ-to-database queries, in that the SQL generated will select only that column.
You just have to select your NumCoefficientFix property before calling FirstOrDefault:
ViewData["Fix"] = db.PreStatusViws
.Where(c => c.LkpNameFix == "1")
.Select(c => c.NumCoefficientFix)
.FirstOrDefault();`
Or in LINQ notation:
ViewData["Fix"] = (from c in db.PreStatusViws
where c.LkpNameFix == "1"
select c.NumCoefficientFix
).FirstOrDefault();

Resources