how can i get ToLower to work in an expression? - linq

I have the following line of code:
protected Expression<Predicate<DuplicateCheck>> Name= x => x.Name == "smith";
when I add a .ToLower()
protected Expression<Predicate<DuplicateCheck>> Name= x => x.Name.ToLower() == "smith";
to try to generalize the query I get the error
System.Reflection.TargetException: 'Non-static method requires a target.'
Is this not available to use in this way?

System.Reflection.TargetException: 'Non-static method requires a
target.'
Normally it happens when the target is null, So you need to check it first like below.
x => x != null && x.Name != null && x.Name.ToLower() == "smith"

Related

Non-Static method requires a target?

I have never seen this error before and its very confusing, I am essentially trying to do something where I say find me all locations (will only return one) that match the location name passed in and the type:
string name = columns[40];
Location type = db.Locations.Where(l => l.name == name).FirstOrDefault();
Location loc = db.Locations.Where(l => l.name == name && l.type == type.type).FirstOrDefault();
There's probably a better way to do what I want in one fell swoop, but essentially I get the name from a column (this comes from a csv file), and then say, get me that locations information. After this I say ok now that I have all that jazz, go get me a location with this name and its type.
But I get the error:
Non-Static method requires a target
The top level method all this code runs in is:
static void Main(string[] args){}
Essentially its just a console app. So whats going on?
db is the context class, this should be obvious.
columns is me pulling the data from the csv file, in this case columns[40] would be something like "New York"
Full Error message from the stack trace: {"Non-static method requires a target."}
Note: The question posted as a "possible answer" does not help in this case as the main method I am running this code in is static.
Upon further investigation I found the name and type were null so I did the following fix:
if (name != null)
{
Location type = db.Locations.Where(l => l.name == name).FirstOrDefault();
Location loc = db.Locations.Where(l => l.name == name && l.type == type.type).FirstOrDefault();
locationNearbyId = loc.id;
// More code
}
Alas I still get the error at: Location loc = db.Locations.Where(l => l.name == name && l.type == type.type).FirstOrDefault();
I had this happen to me today. Come to find out, I was doing this:
Player player = db.Players
.Where(p => p.ClubID == course.Club.ID && p.IsActive == true && p.Phone != null)
.ToArray()
.SingleOrDefault(p => p.Phone.FormatPhoneNumber() == phone);
where course.Club was being lazy-loaded via EF from my database. At first, I thought my problem was the FormatPhoneNumber extension, but then found that removing the course.Club.ID fixed the issue:
int clubID = course.Club.ID;
Player player = db.Players
.Where(p => p.ClubID == clubID && p.IsActive == true && p.Phone != null)
.ToArray()
.SingleOrDefault(p => p.Phone.FormatPhoneNumber() == phone);
So, avoid using values gleaned from lazy-loaded objects in subsequent LINQ queries - assign them to local variables and then use those variables in your query.
Turns out that because name and type can be null type has to be set out side the if statement and thus i must check if type and name are null before continueing:
name = collumns[40];
type = db.Locations.Where(l => l.name == name).FirstOrDefault();
if (name != null && type != null)
{
Location loc = db.Locations.Where(l => l.name == name && l.type == type.type).FirstOrDefault();
//More code....
}
It is a fact that the problem is due to the null "type" object.
I would solve this way:
var tType = type?.type;
Location loc = db.Locations.Where(l => l.name == name && (type != null && l.type == tType)).FirstOrDefault();

How can I check for null values in this linq query where clause

I have a linq query to locate a matching item in a SharePoint library. It works fine if there is a custom property called 'MMSTerm' but if the property is null then obviously my string modifications will fail and error out when it hits x["MMSTerm"]
I will need to use string.replace in my where operation so a null won't be good.
SPListItem item = (from x in Items.OfType<SPListItem>()
where x["MMSTerm"].ToString() == pageReference.ToString()
select x).ToList<SPListItem>().FirstOrDefault();
Hopefully this is an easy one.
You can verify if field exists with SPFieldCollection.ContainsField method
SPListItem item = (from x in Items.OfType<SPListItem>()
where x.Fields.ContainsField("MMSTerm") &&
(x["MMSTerm"] == null ||
x["MMSTerm"].ToString() == pageReference.ToString())
select x).FirstOrDefault();
Also I think fluent API looks better in this case:
SPListItem item = Items.OfType<SPListItem>()
.FirstOrDefault(x =>
x.Fields.ContainsField("MMSTerm") &&
(x["MMSTerm"] == null ||
x["MMSTerm"].ToString() == pageReference.ToString()));
Since calling x["MMSTerm"] throws an exception when "MMSTerm" does not exist, rather than returning null, you should call ContainsField
x.Fields.ContainsField("MMSTerm")
to see if the field is there:
SPListItem item = (from x in Items.OfType<SPListItem>()
where x.Fields.ContainsField("MMSTerm") && x["MMSTerm"].ToString() == pageReference.ToString()
select x).FirstOrDefault();
Since && short-circuits evaluation when x.Fields.Contains("MMSTerm") is false, the x["MMSTerm"] would not be evaluated.
In case the x["MMSTerm"] could contain nulls, you could use the ""+obj trick to avoid null reference exceptions:
var pageRefStr = pageReference.ToString();
SPListItem item = (from x in Items.OfType<SPListItem>()
where x.Fields.ContainsField("MMSTerm") && pageRefStr.Equals(""+x["MMSTerm"])
select x).FirstOrDefault();

Why am I geting this error: Operator ā€˜&&ā€™ cannot be applied to operands of type System.Linq.IQueryable?

Iā€™m trying to retrieve data from an entity and populate a viewModel property like this:
viewModel.Enrollments = db.Enrollments.Where(b => b.classDays == "Monday") && (db.Enrollments.Where(b => b.CourseID == courseID);
but I get a operator && cannot be applied to operands of type System.Linq.IQerable<> error. Can you help with a way to find all Monday class with the same ID?
I tried this: viewModel.Enrollments = db.Enrollments.Where(b => b.classDays == "Monday") but I get all Mondays courses but I want to limit them to a specific courseID.
Please help!
You need to examine your parentheses. This code won't even compile:
viewModel.Enrollments = db.Enrollments.Where(b => b.classDays == "Monday")
&& (db.Enrollments.Where(b => b.CourseID == courseID);
In that code you're trying to use && between two calls to .Where(), which return an IQueryable. You probably mean to use && within the .Where() clause:
viewModel.Enrollments = db.Enrollments.Where(b => (b.classDays == "Monday")
&& (b.CourseID == courseID));
Or perhaps append a second .Where() clause:
viewModel.Enrollments = db.Enrollments.Where(b => b.classDays == "Monday")
.Where(b => b.CourseID == courseID);
Note that .Where() can be chained indefinitely, essentially resulting in applying each clause in turn in an AND fashion in the resulting query.
&& Operator should be used with conditions inside where NOT with sets of enrollments (in your case)
Try This:
viewModel.Enrollments = db.Enrollments.Where(b => (b.classDays == "Monday") && (b.CourseID == courseID));

LINQ Lambda Where() not filtering as expected

I'm trying to build a query using LINQ for EF to filter results based on some basic logic. For some reason, even with the following Where() functions being executed and setting the right parameters, all data is being returned instead of the filtered results from Where().
I have run debug to make sure that my if() statements are indeed allowing the Where() to run when appropriate, and it is.
What am I missing?
var dbReports = db.SubmitReports;
if (Referee != String.Empty)
dbReports.Where(u => (u.Refree == Referee || u.Ar1Official == Referee || u.Ar2Official == Referee || u.FourthOfficial == Referee));
if (TeamName != String.Empty)
dbReports.Where(u => (u.HomeTeam == TeamName || u.VisitingTeam == TeamName));
if (PlayedOnStart != DateTime.MinValue && PlayedOnEnd != DateTime.MinValue)
dbReports.Where(u => (u.PlayedOn >= PlayedOnStart && u.PlayedOn <= PlayedOnEnd));
if (StateAssociation != String.Empty)
dbReports.Where(u => (u.StateAssociation == StateAssociation || u.StateAssociation2 == StateAssociation));
if (Division != String.Empty)
dbReports.Where(u => u.Division == Division);
if (ProfessionalLeague != String.Empty)
dbReports.Where(u => u.ProfessionalLeague == ProfessionalLeague);
if (AgeGroup != String.Empty)
dbReports.Where(u => u.AgeGroup == AgeGroup);
return dbReports.ToList();
Where doesn't modify the existing query - it creates a new query. You need to assign the result of the call to Where to something otherwise the result is simply discarded. Try this:
IQueryable<Report> dbReports = db.SubmitReports;
if (...)
{
dbReports = dbReports.Where(...);
}
You never use the return value of the Where method. Where does not modify the IEnumerable it is apply on but returns a Linq expression that will create a modify IEnumerable when executed (i.e when ToList is called).

How to programmatically set label text - Linq To Entities

I have to set the label text of a load of differnet labels on a web page based upon user preferences.
I have the following code that is place upon the label load event (probably wrong!)
string memberid = Session["MemberID"].ToString();
string locationid = Session["LocationID"].ToString();
string userName = Membership.GetUser().UserName;
string uuf1 = "UnitUserField1";
MyEntities lblUUF1Text = new MyEntities();
lblUUF1.Text = lblUUF1Text.tblUserPreferences
.Where(p => p.MemberID == memberid && p.LocationID == locationid && p.Username == userName && p.ColumnName == uuf1)
.Select(p => p.Alias)
.ToString();
However when I run this, the label text returned is:
System.Data.Objects.ObjectQuery`1[System.String]
Can someone point me in the error of my ways. I'm feeling very, very thick at the moment.
You're writing a query and then asking that query to be converted to a string. Do you only want the first result of that query? If so, it's easy:
lblUUF1.Text = lblUUF1Text.tblUserPreferences
.Where(p => p.MemberID == memberid &&
p.LocationID == locationid &&
p.Username == userName && p.ColumnName == uuf1)
.Select(p => p.Alias)
.First();
(I'm assuming that the type of p.Alias is already string, but that you included the call to ToString as an attempt to coerce the query into a string to make it compile.)
Note that if there are no results, that will blow up with an exception. Otherwise it'll take the first result. Other options are:
Sure there's exactly one result? Use Single()
Think there's either zero or one? Use SingleOrDefault(), store in a local variable and set the label text if the result isn't null.
Think there's anything from zero to many? Use FirstOrDefault() in the same way.
You need a .First() in there
lblUUF1.Text = lblUUF1Text.tblUserPreferences
.Where(p => p.MemberID == memberid && p.LocationID == locationid && p.Username == userName && p.ColumnName == uuf1)
.Select(p => p.Alias).First().ToString();
ToString() will return the object type as you see, what you will need to do is this:
lblUUF1.Text = lblUUF1Text.tblUserPreferences
.Where(p => p.MemberID == memberid && p.LocationID == locationid && p.Username == userName && p.ColumnName == uuf1)
.Select(p => p.Alias).SingleOrDefault();

Resources