search list in where with and condition - c#

I has a table Project
id|title
___________________
1|water blue
2|test water blue low test
3|low blue
I has a list Search(Search list is dynamic and fill with user with any value and with any number row)
string[] search = new string[] { "water", "blue", "low" };
I want write this query with ef6
select * from project
where title like '%water%' and title like'%blue%' and title like '%low%'
I write this code but this return all row (i want only row 2 water blue low)
var result = (from p in context.project
where seartch.Contains(p.title)
select p
).ToList();
Please help me

Try something like this
var result = search.Where(x=>x.Contains("water") || x.Contains("blue")).ToArray();
Array.ForEach(result, Console.WriteLine);
UPDATE
var result = context.project.Where(x=>Array.IndexOf(search, x.Title) > -1);

You could try this
You will only get the row 2. As it take consideration of matching all records in your search string.
from p in context.project
.Where(g => search.All(h => g.Title.Contains(h)));

Your current query is the wrong way around. The equivalent SQL would be
WHERE title IN ('water', 'blue', 'low')
The correct query can be built by iterating over the array of search terms, and create a where term for each. The terms are implicitly AND'ed by linq:
IQueryable<Project> query = context.project;
foreach (var s in search) {
query = query.Where(x => x.Title.Contains(s));
}
var result = query.ToList();

By SQL-like query
var result = (from p in context.project
where (p.title.Contains(search[0])& p.title.Contains(search[1])&p.title.Contains(search[2])
).ToList();
By lambda exp
var result= context.project.Where(p=>p.title.Contains(search[0])&p.title.Contains(search[1])&p.title.Contains(search[2])).ToList();

You can achieve it in this way
var query = from p in context.project;
foreach(var item in search)
query.Where(p => p.Title.Contains(item));
var result = query.ToList();

Related

How do I drill down to specific data in my LINQ query result?

I want to drill down into a particular item in my data and output the list of results to the output window. My query result looks like this
private IEnumerable<DataRow> _data;
var query = from data in this._data
group data by data.Field<string>("Form Name") into groups //same as Form ID
select new
{
formName = groups.Key,
items = from d in groups
group d by d.Field<string>("Item Name") into grps
let name = grps.Key
let documentIDGroups = grps.GroupBy(t => t.Field<string>("Document ID"))
let documentIDGroupsCount = documentIDGroups.Count()
let distinctDocumentValueCount = from data in documentIDGroups
select new
{
docID = data.Key,
distinctDocValueCount = data.Where(t => string.IsNullOrEmpty(t.Field<string>("Document Value").Trim()) == false).Select(t => t.Field<string>("Document Value")).Distinct().Count()
}
let sum = distinctDocumentValueCount.Sum(t => t.distinctDocValueCount)
let distinctItemsNames = from data in grps
select data.Field<string>("Item Name").Distinct().Count()
let count = distinctItemsNames.Count()
select new
{
itemName = name,
documentIDGroups,
documentIDGroupsCount,
averageChoices = Math.Round(((decimal)sum / documentIDGroupsCount), 2),
distinctDocumentValueCount,
sum
}
};
So on that query result I want to drill down into a particular form name, and from there get a particular Item Name and so on
so the first step is to get the grouping of items and I have
var items = from d in query where d.formName == "someName" select d.items;
but I don't know how to isolate the items by a particular string.
I want to do the following
var item = from d in items where d.itemName == "anItemName" select d;
But I don't know the syntax.
Use the .FirstOrDefault extension if you expect a single item to be returned from your query. SO:
var item = (from d in items where d.itemName == "anItemName" select d).FirstOrDefault();

Returning List<string> from Linq query returns query syntax not values

I have the below code to return a list of strings.
public List<string> Top5CodesForToday()
{
var date = DateTime.Now;
var resultList = new List<string>();
using (var db = new PillowContext())
{
var qry = (from d in db.DownTimes
where DbFunctions.TruncateTime(d.DateTime) == DbFunctions.TruncateTime(date)
group d by new {d.Code}
into g
let total = g.Sum(x => x.Amount)
orderby total descending
let top5 = g.Take(5).ToList()
select new {g.Key.Code, Total = total});
foreach (var item in qry)
{
int x = item.Code;
var results = from r in db.DownTimeCodes
where r.Code == x
select r.Description;
resultList.Add(results.ToString());
}
}
return resultList;
}
When I look at the contents of returnList I am seeing the correct number of items however each item is made up of the actual query syntax, not the data itself. I have seen this before and usually solve it by doing .ToList() however I am unsure how I could change my code to solve this
The problem here is that when you are calling ToString the query is not executed yet, so essentially you are calling ToString on a IQueryable object, receiving the query instead of results. You need to call something to execute the query.
You can call ToList() still:
var results = (from r in db.DownTimeCodes
where r.Code == x
select r.Description).ToList();
resultList.AddRange(results);
Or, if you expect just one result, call FirstOrDefault()/SingleOrDefault():
var results = (from r in db.DownTimeCodes
where r.Code == x
select r.Description).FirstOrDefault();
resultList.Add(results);
You are calling ToString() on List<>. As default for most complex types, it just writes out type name not the data.
This line
resultList.Add(results.ToString());
should be changed to
resultList.AddRange(results);

linq-to-sql getting sequence contains more than one element

I have a query that looks like this: it takes a list of IDs (ThelistOfIDs) as parameter and I'm grouping for a count.
var TheCounter = (from l in MyDC.SomeTable
where ThelistOfIDs.Contains(l.ID)
group l by l.Status into groups
select new Counter()
{
CountOnes = (from g in groups
where g.Status == 1
select g).Count(),
CountTwos = (from g in groups
where g.Status == 2
select g).Count(),
}).Single();
And basically, I don't understand why I'm getting the error. I don't want to brring back the entore collection from the DB and do the count in linq-to-object; I want to do the count in the DB and bring back the result.
I have not put your query into my IDE or compiled with C#, but I guess the problem is that
groups in your query is IGrouping<Tkey, Telm> and not IQueryable<Tkey>
(where Tkey is type of l.Status and Telm is type of l).
I think you got confused with the use of grouping operator.
What you want to get is I guess:
var queryByStatus = from l in MyDC.SomeTable
where ThelistOfIDs.Contains(l.ID)
group l by l.Status;
var counter = new Counter()
{
CountOnes = queryByStatus.Where(l => l.Key == 1).Count(),
CountTwos = queryByStatus.Where(l => l.Key == 2).Count(),
};
EDIT:
Alternative query, to obtain the same, moving all operation on DB into the original query so that DB is queried only once.
var queryCountByStatus = from l in MyDC.SomeTable
where ThelistOfIDs.Contains(l.ID)
group l by l.Status into r
select new { status = r.Key, count = r.Count() };
var countByStatus = queryCountByStatus.ToList();
var counter = new Counter()
{
CountOnes = countByStatus.FirstOrDefault(l => l.status == 1).count,
CountTwos = countByStatus.FirstOrDefault(l => l.status == 2).count,
};
Note:
The query in my edit section queries the DB once only and mapping Status -> Count is returned.
Note that in my original query there were two calls to DB needed only - both of which returned single number - one for CountOnes, one for CountTwos.
In the edit query, one query is done which return table { { 1, CountOnes}, {2, CountTwos } }. The other lines are just to convert the result - which is set of items - into single object having certain objects as properties and is done physically on these two values.
You are grouping by Status, and then projecting from that group - but you will still have one row per unique Status (===group).
So: I propose that you don't have exactly one unique Status.
This might be what you're looking for to get...
(it's for users table I had but should be the same)
var statuscounts = (from u in db.Users
where u.UserStatus > 0
group u by u.UserStatus into groups
select new { Status = groups.Key, Count = groups.Count() });
// do this to iterate and pump into a Counter at will
foreach (var g in statuscounts)
Console.WriteLine("{0}, {1}", g.Status, g.Count);
...or even something like this...
var counter = statuscounts.AsEnumerable()
.Aggregate(new Counter(), (c, a) => {
switch (a.Status)
{
case 1: c.CountOfOnes = a.Count; return c;
case 2: c.CountOfTwos = a.Count; return c;
case 3: c.CountOfThrees = a.Count; return c;
default: c.CountOfOthers = a.Count; return c;
}});
...point is that if you're grouping already you should use the grouping result, it's of type IGrouping<out TKey, out TElement> where the key is your status and it's IEnumerable<> or your records.
hope this helps

Use Any() and Count() in Dynamic Linq

I am trying to write dynamic Linq Library query to fetch record on condition,
Customers who has order count is greater than 3 and ShipVia field equal 2.
Below is my syntax what i have tried.
object[] objArr = new object[10];
objArr[0] = 1;
IQueryable<Customer> test = db.Customers.Where("Orders.Count(ShipVia=2)", objArr);
and
IQueryable<Customer> test = db.Customers.Where("Orders.Any(ShipVia=2).Count()", objArr);
But both are not working. In second query Any returns true so it won't work with Count.
Suggest me a way to implement this.
If you HAVE to use Dynamic Linq, your query should look like that:
db.Customers.Where("Orders.Count(ShipVia == 2) > 3");
How about something like this.
IQueryable<Customer> test = db.Customers.Where(c => c.Orders.Where(o => o.ShipVia ==2).Count() >2);
var grp = db.Customers.Where("ShipVia=2").GroupBy("ShipVia");
var test = from a in grp
where a.Count() > 3
select a.Key;
IQueryable<Customer> test =
from c in db.Customers
from o in c.Orders
where o.ShipVia == 2 // NOTE you need == not = for compare
group c by c into grp
select new {customer = grp.key, ordercount = grp.Count() };
Untested but I believe this should do it all in one statement, assuming Orders are a collection within Customer.
Note that your single = in your where clause is very dangerous as it'll assign 2 to all shipvias instead of test (==)

Getting Only The Top Row From Each Group

I have some code that groups a table by "Value1" and some loops that add the top row of each group to a list. This is a pretty ugly way to do this, and I was wondering if I could replace one of the foreach loops with a couple more lines in my LINQ query? Problem is, I don't have the foggiest idea how to do this.
var Result =
from a in DB.Table1
group new {Values = a} by a.Value1 into c
select new {everything = c};
foreach (var Row in Result)
{
foreach (var RowAll in Row.Everything)
{
List.Add(new List<string>() {RowAll.Value1, RowAll.Value2})
break;
}
}
Use Enumerable.First:
var List =
(from Row in Result
let RowAll = row.Everything.First()
select new List<string>() {RowAll.Value1, RowAll.Value2}
).ToList();
Or, combined with your original query:
var List =
(from a in DB.Table1
group a by a.Value1 into c
select new List<string>() {c.Key, c.First().Value2}
).ToList();
Use FirstOrDefault:
var query = from row in result
let rowAll = row.Everything.FirstOrDefault()
where rowAll != null
select new List<string> {rowAll.Value1, rowAll.Value2};
var list = query.ToList();
Rereading you first query I realised you are grouping on a property of 'a' so there should be no empty groupings. First() should be safe as in the other posters example.

Categories