Search for any word in a Linq query - asp.net

I'm passing a string to a controller, and need the controller to search for ANY of the words passed, within the Title field of my database.
eg. id="outlook error message"
[HttpPost]
public JsonResult Lookup(string id)
{
List<string> listOfSearch = id.Split(' ').ToList();
var results = db.KS.Where(x => x.Title.Intersect(listOfSearch).Any());
This produces the following two errors:
Instance argument: cannot convert from 'string' to 'System.Linq.IQueryable<string>
'string' does not contain a definition for 'Intersect' and the best extension method overload 'System.Linq.Queryable.Intersect<TSource>(System.Linq.IQueryable<TSource>, System.Collections.Generic.IEnumerable<TSource>)' has some invalid arguments
Can anyone please advise what's wrong, or how to populate results with just a list of Titles that contain any of the words passed in?
Thanks, Mark

var results = db.KS.Where(x => listOfSearch.Any(item => x.Title.Contains(item)));
Update:
For LinqToSql:
var titles = db.KS.Select(item => item.Title)
.AsEnumerable()
.Where(title => listOfSearch.Any(word => title.Contains(word)));

you can try
List<string> listOfSearch = id.Split(' ').ToList();
var result = from item in db.KS
where listOfSearch.Any(v => item.Title.Contains(v))
select item;
or
var result = db.KS.Where(item => listOfSearch.Any(v => item.Title.Contains(v)));

Change the statement to:
db.KS.Intersect(....
KS returns you the IQueryable on which you can directly perform the intersection.

Related

SelectMany doesn't work on cosmosDb for child properties?

When I try to use selectMany on queryable that I build against cosmosdb I always get exception:
The LINQ expression 'DbSet
.Where(t => t.Id == __timelineId_0)
.SelectMany(
source: t => EF.Property>(t, "GraduationEvents")
.AsQueryable(),
collectionSelector: (t, c) => new TransparentIdentifier(
Outer = t,
Inner = c
))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
The query doesn't matter, always when I use selectMany I get this error.
Example query:
await _dbContext.Timelines.Where(x => x.Id == timelineId).Select(x => x.GraduationEvents).SelectMany(x => x).ToListAsync();
My entity configuration:
public void Configure(EntityTypeBuilder<Timeline> builder)
{
builder.HasKey(x => x.Id);
builder.HasAlternateKey(x => x.Id);
builder.OwnsMany(x => x.GraduationEvents, x => x.OwnsMany(graduationEvent => graduationEvent.Subjects));
}
I also tried to use native cosmosClient but when I query the base with plain sql I get empty objects (all nulls). Any thoughts what am I doing wrong?
Sajid - I tried your soulution but the exception remains the same
Try calling directly .SelectMany() over the List property (GraduationEvents).
I usually then call AsDocumentQuery() to generate the query to CosmosDB and then execute that query to retrieve the results.
Some pseudo c# to clarify this a bit:
var query = this.documentClient.CreateDocumentQuery(uri, options)
.SelectMany(x => x.GraduationEvents).AsDocumentQuery();
List<T> results = new List<T>();
while (query.HasMoreResults)
{
results.AddRange(await query.ExecuteNextAsync());
}
Edit: This approach uses the native Azure DocumentClient library.

Trouble with LINQ Returning Results Set from Object[] Array Within Object

Consider the following code:
var articlesDisplay = from product in db.ProductSearchData
select product.articles;
articlesDisplay = articlesDisplay.Where(a => a[].body.Contains(searchString));
I'm trying to load a results set, but get a compiler error using the array notation in the Where clause. How should I be going about this?
The desired end result is a var articlesDisplay object that can be used in ASP.NET MVC pagination.
Thanks to any/all for your assistance!
remove the array notation
var articlesDisplay = from product in db.ProductSearchData
select product.articles;
articlesDisplay = articlesDisplay.Where(a => a.body.Contains(searchString));
A lambda expression is just like a function declaration, but instead of method name(paramters){body } it takes the form of parameters => body. So this:
a => a[].body.Contains(searchString)
Is the same as this:
bool Method(Article article)
{
return article[].body.Contains(searchString);
}
That is obviously not valid, since it won't compile. You need a Func<T,bool>, or a function that accepts a single element and returns true or false depending on whether it is to be included. So you probably want this:
bool Method(Article article)
{
return article.body.Contains(searchString);
}
Which translates to this:
a => a.body.Contains(searchString).

JsonResult from lambda expression using join

I am using the following Lambda expression to try and join two models (LyncUser) and (DDI) and only return the DDI numbers that exist in both models. In LyncUser the field is called LyncUser.DDI and in DDI it is called DDI.Number.
This works and returns a list of all DDI numbers that are used from LyncUsers controller.
var lyncDB = new LyncUserEntities();
return Json(lyncDB.lyncUsers
.Select(c => new { DDI = c.DDI }), JsonRequestBehavior.AllowGet);
When I change this to incorporate a join so only the DDI numbers are returned that exist in LyncUsers but do not exist in DDI it fails to bring anything back.
public JsonResult GetAvailableDDINumbers()
{
var lyncDB = new LyncUserEntities();
return Json(lyncDB.LyncUsers
.Join(lyncDB.DDIs, avail => avail.DDI, used => used.Number,
(used, avail) => new { used = used, avail = avail })
.Where(joined => joined.used.DDI == joined.avail.Number), JsonRequestBehavior.AllowGet);
}
only the DDI numbers (...) that exist in LyncUsers but do not exist in DDI
To me that means you want to return LyncUsers having a DDI that doesn't exist as DDI.Number.
Your code, an inner join, does exactly the opposite. It returns the entities where both values (DDI and Number) are equal. And apparently, at this moment, there aren't any meeting this condition.
To achieve what you want you should use a different statement:
return Json(lyncDB.LyncUsers
.Where(u => !lyncDB.DDIs.Any(ddi => ddi.Number == u.DDI)), JsonRequestBehavior.AllowGet);
This should currently return all lyncDB.LyncUsers.
I don't think you need Join at all as you are not using joined result.
Try this instead:
var lyncDB = new LyncUserEntities();
var result = lyncDB.lyncUsers
.Where(x => !lyncDB.DDIs.Any(y => y.Number == x.DDI))
.Select(x => new { DDI = x.DDI });
return Json(result, JsonRequestBehavior.AllowGet);
Also, split your code in multiple lines as #Nate Barbettini advises in comment. This will allow to inspect results in debug mode and to better understand what is going on.

Linq Query Distinct Function do not work with DropdownList

I want to assign Linq Query result to dropdownlist which contain a
Distinct function
My Code:-
var area = de.City_Area_View
.Select(m => new { m.Area_Id, m.Area_Name})
.Distinct()
.ToList();
drpfilter.DataTextField = "Area_Name";
drpfilter.DataValueField = "Area_Id";
drpfilter.DataSource = area;
drpfilter.DataBind();
Problem :- When I write this code then I get Below Error
Error:- The method 'Distinct' is not supported.
I get System.NotSupportedException.
I want to assign a Distinct name of area to the DropDownList
So please help me for this problem.
If your set is small enough (so you don't mind fetching all the values from the database), the simplest thing would be to force the distinct part to be performed locally:
var area = de.City_Area_View
.Select(m => new { m.Area_Id, m.Area_Name})
.AsEnumerable()
.Distinct()
.ToList();
AsEnumerable simply "changes" the expression type to IEnumerable<T> instead of IQueryable<T>, so that the compiler calls Enumerable.Distinct instead of Queryable.Distinct - and Enumerable.Distict will definitely work.

Linq Query with .Any condition returns nullreference exception

I have the following function that returns results from the database based on LINQ Expressions:
IQueryable<TEntity> FindAll<TEntity>(Expression<Func<TEntity, bool>> expression)
When I try pulling data from the function while using the .Any function from a list I get a null reference exception.
However when I pull the data without that specific condition and use the same .Any function in a for each loop everything works correctly.
Here is the call trying to use the .Any function which does not work:
var ppcReports = repository.FindAll<PPCReport>(
x => x.ClientId == clientId &&
(campaigns.Any(c=> c.Id == x.CampaignId))
).ToList();
And the way it does work properly:
var ppcReports = repository.FindAll<PPCReport>(
x => x.ClientId == clientId).ToList();
foreach (var item in ppcReports)
{
if (campaigns.Any(c => c.Id == item.CampaignId))
{
// do something
}
}
I was wondering why was this happening, am I doing something wrong is it just not possible to filter the results before the query finished?
By calling .ToList() before filtering the results it does work, so I suppose I cannot do such an operation on an IQueryable<T> implementation?
var ppcReports = repository.
FindAll<PPCReport>(x => x.ClientId == clientId).
ToList().
Where(w => campaigns.Any(c => c.Id == w.CampaignId)).
ToList();
Like those who commented, I'm surprised that you got a NullReferenceException rather than a complaint about not being able to compile that statement to SQL. However, the following code should let you do this in 1 query (and will do all filtering in SQL):
var campaignIds = (campaigns ?? Enumerable.Empty<Campaign>())
.Select(c => c.Id);
var ppcReports = repository
.FindAll<PPCReport>(pr => pr.ClientId == clientId
&& campaignIds.Contains(pr.CampaignId))
.ToList();
This should work in both EF and Linq-to-SQL.
Queryable.Any() returns an ArgumentNullException when the source is null, as documented here: https://msdn.microsoft.com/it-it/library/bb343630(v=vs.110).aspx

Resources