Where clause like syntax in lambda expression - asp.net-mvc-3

I searched alot but couldnt find the right resolution for my problem.
What i'm trying is very basic in sql but dont know how to make it work in lambda expression here is what im trying to do:
FilteredInOrderquery = mycontext.Websites.OrderBy(website.currentOrderBy + " " + website.sortOrder).Where(
x => (website.websiteFilterList.Contains(x.site.ToString()))
&&
(website.cityFilterList.Contains(x.city.ToString()))
).Select(x => new WebsiteData(
x.RowID,
x.pagetype,
x.site,
x.creationdate ?? DateTime.Today,
x.expirationdate ?? DateTime.Today,
x.domainregistrar,
x.pin,
x.area,
x.city,
((x.expirationdate ?? DateTime.Today) - DateTime.Today).Days.ToString() + " days"));
websitefilterList and cityFilterlist both can be empty as well as can contain more than one item.
Point is that i should be able to get records even if i pass any of the list as empty (if list is empty then i should get all records of that column)
and if im passing both list with more than one entry ..records matching with those entries only should appear.
currently this is not happening i get error when any of my list is empty. although if any of list is empty then i must get all the records. this is very common requirement but i couldnt find the solution.

Where(x =>
(!website.websiteFilterList.Any() || website.websiteFilterList.Contains(x.site.ToString()))
&&
(!website.cityFilterList.Any() || website.cityFilterList.Contains(x.city.ToString())))

Related

How to search for substring in a list of strings in episerver find

I have a list of strings like this
"Users": [
"usrName|Fullname|False|0|False|False",
"usrName|Fullname|False|0|False|False",
"usrName|Fullname|False|0|False|False",
"usrName|Fullname|False|0|False|False",
"usrName|Fullname|False|0|False|False",
]
In my episerver/optimizely code I want to match items. I have written this line of code
searchResult.Filter(x => x.Users.MatchContained(k=> k.Split('|')[3], "0"));
I am trying to get all Users where after splitiing on 'pipe' I get 0 at index 3. I am not getting the result, infact I get an exception.
What am I doing wrong here?
Since you left out A LOT of details these are my assumptions
Users is an IList<string> Users
You are trying to get all Users within that list/array where index 3 equals 0
What we don't know is, among others
Is there more than one page instance that have the Users instance filled?
Anyway, this cannot be solved using any Find API with the current system design. Instead you need to rely on linq to parse the result, but then the Find implementation may not be necessary.
var searchClient = SearchClient.Instance;
var search = searchClient.Search<BlogPage>();
var result = search.GetContentResult();
var usersResult = result
.SelectMany(x => x.Users)
.Where(x => x.Split('|')[3].Equals("0"));
This would create and return an object similar to this, since I'm using SelectMany the array would contain all users throughout the systems where there are matched pages from the search result.
If you for whatever reason would like to keep or see some page properties there are alternative approaches where you construct a new object within a select and remove any object where there where not matched users
var searchClient = SearchClient.Instance;
var search = searchClient.Search<BlogPage>();
var result = search.GetContentResult();
var usersResult = result
.Select(p => new
{
PageName = p.Name,
ContentLink = p.ContentLink.ToString(),
Users = p.Users.Where(x => x.Split('|')[3].Equals("0"))
})
.Where(x => x.Users.Any());
If you like to keep using Find for this kind of implementations you must store the data in a better way than strings with delimiters.

Select multiple columns for AutoComplete result using LinQ

I'm setting up an AutoComplete function that will return a list of Holdings with associated Codes. (e.g. Google GOOGL, Amazon AMZ, etc)
I am able to get the results using the following code:
var names = _context.UMA
.Where(p => p.Name.Contains(term) || p.Code.Contains(term))
.Select(p => p.Name );
This code works and returns a list of Holding Names.
I now want to add the Holding Codes in the result.
I changed the last line of Code to this:
.Select(p => new {p.Code, p.Name})
But the result only shows blank lines (but the correct number of blank lines.)
If I change the last line to just this:
.Select(p => new { p.Name})
I still get blank lines (and, yes, correct number of blank lines.)
Any help always appreciated!

Finding if value exists in list with LINQ and saving info into a dataset, possibly

i am brand new to LINQ, i currently have a look that loops through all orgs that a user belongs to, to make sure they have permissions to do various operations on the form.
looks something like this:
//loop through all user orgs to see if what they selected, they have access to
foreach (OrgPermission userOrg in user.orgs)
{
//get the org permissions for the selected org
if ((ddlOrg.SelectedValue == (userOrg.Org.orgCode + "-" + userOrg.Org.orgSubCode)))
{
if (userOrg.type.Contains("3") || userOrg.type.Contains("00"))
{
/
/do something here.
}}}
i am trying to get rid of the loop. as if the user has lots of orgs it's taking a little while to run, and i'm trying to optimize application run time.
i tried the following:
bool has = user.orgs.Any(cus => cus.Org.orgCode + "-" + cus.Org.orgSubCode == ddlOrg.SelectedValue);
as you can see, the ddlOrg dropdown value are in org-suborg format. but i'm always getting false.
i would also like to save the result, not in a bool, but possibly as a single user.ORG that it found, so that i can use that to then check permissions and other stuff.
am i on the right track here? could someone please point me in the right direction.
You typically wouldn't get rid of the loop, but rather filter the items that are being looped:
var users = user.orgs.Where(userOrg => ddlOrg.SelectedValue == (userOrg.Org.orgCode + "-" + userOrg.Org.orgSubCode) && (userOrg.type.Contains("3") || userOrg.type.Contains("00")));
foreach(OrgPermission userOrg in users)
{
// do your operation
}
That being said, this is likely not going to be much faster, as the LINQ query is still effectively looping through your items, but it will potentially be simpler to maintain.
If you only need to look for a single OrgPermission (ie: the first), you could speed this up via:
var userOrg = user.orgs.FirstOrDefault(userOrg => ddlOrg.SelectedValue == (userOrg.Org.orgCode + "-" + userOrg.Org.orgSubCode) && (userOrg.type.Contains("3") || userOrg.type.Contains("00")));
// userOrg will be the OrgPermission if found, or null if not.

LINQ - Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator

This seems to be about the most generic error I've come across - multiple SO posts about it are all referring to different issues - well here's a new one :)
I get the error above when the following IQueryable is enumerated:
N.B. items is an IQueryable<tblItem> and keywords is a string
items = items.Where(p => p.heading.ToLower().Contains(keywords) ||
p.description.ToLower().Contains(keywords));
This is confusing because, as the error suggests, it should work fine when you use a Contains - does anyone know how to fix this?
If keyword is a collection that supports enumeration, then it should be other way around:
items = items.Where(p => keywords.Contains(p.heading.ToLower()) ||
keywords.Contains(p.description.ToLower()));
If items is IQueryable then the error may be there and nothing to do with your where statement.
Can you try forcing enumeration before adding your where statement?
For example, suppose you are attempting to join an in memory list with a datatable you will get that error when the query is evaluated or enumerated
List<tblCategory> categories = tblCategory.ToList();
IQueryable<tblItem> items = (from r in tblItem
join c in categories on r.CategoryID equals c.Id select r);
// items = items.Where(p => p.heading.ToLower().Contains(keywords) ||
// p.description.ToLower().Contains(keywords));
var firstMatch = items.FirstOrDefault();
// The error will be generated here even if the where is remmed out
SOLVED
Thanks sgmoore for your input - it helped arrive at this solution:
Assgning the IQueryable list to an IEnumerable list, running a ToList on it and THEN using my filters on the list worked great.
IEnumerable<tblItems> temp = items.ToList();
temp = temp.Where(p => p.heading.ToLower().Contains(keywords) ||
p.description.ToLower().Contains(keywords));
items = temp.AsQueryable();

LINQ Dynamic Expression API, predicate with DBNull.Value comparison

I have an issue using the Dynamic Expression API. I cannot seem to compare a DataTable field against DBNull.Value. The API is supposed to be able to "support static field or static property access. Any public field or property can be accessed.". However given the following query:
var whatever = table1.AsEnumerable()
.Join(table2.AsEnumerable(),
(x) => x.Field<int>("Table1_ID"),
(y) => y.Field<int>("Table2_ID"),
(x, y) => new { x, y})
.AsQueryable()
.Where("x[\"NullableIntColumnName\"] == DBNull.Value");
I end up getting the error: "No property or field 'DBNull' exists in type '<>f__AnonymousType0`2'"
Anyone have ideas on how to get around this? I can't use Submission.Field("NullableIntColumnName") in the string passed to the Where method either, btw, or else I would be able to compare against null instead of DBNull.Value.
Well, I finally got it. cptScarlet almost had it.
var values = new object[] { DBNull.Value };
...
.Where("x[\"NullableIntColumnName\"] == #0", values);
or
.Where("x[\"NullableIntColumnName\"] == #0", DBNull.Value);
What happens when you replace your current .Where with something like
.Where(string.format("x[\"NullableIntColumnName\"] == {0}",DBNull.Value));
If you change x.Field<int>("Table1_ID") to x.Field<int?>("Table1_ID") then you'll get nullable integers instead of regular integers, and any DBNull values will be converted to simple C# null values. Based simply on your code snippet, I'm not even sure you'd need dynamic expressions - a simple .Where(foo => foo.x == null) ought to work.
In general, you can also try:
.Where("NullableColumnName.HasValue");
Sorry to non-answer with a USL but...
Have you looked in the source? There's not a lot of it. My guess is that DBNull is not in the list of registered root objects.
I dont have the source to hand right now, but it is also likely to tell you what any other constants one might compare against might be.
.Where(a => a.IntColName == null);
Edit:
Sorry, I did't see this dynamic requirement... Dynamic would be: (at least in Framework 4)
var intColName = "...";
.Where(string.Format("it.{0} is null", intColName));

Resources