Non-Static method requires a target? - linq

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();

Related

LINQ EF AND VS2017

I wrote a query and worked on LINQPAD
from x in FacilityData
from y in FavInformation
where y.UserID == 1 && x.ID == y.FacilityID
select new
{
xID = x.ID,
xDistrictName = (from y in _Ilcelers
where y.ID == x.DistrictID
select y.IlceAd).FirstOrDefault(),
xName = x.Name,
Value = (from o in Tags
from p in Table_tags
where o.Prefix != null && o.Prefix == p._NAME && o.Facility == y.FacilityID
orderby p.İd descending
select new
{
FType = o.TagType,
Name = o.TagsName,
Value = p._VALUE,
Time = p._TIMESTAMP
}).Take(Tags.Count(h => h.Facility == y.FacilityID))
}
result
the result is perfect
but does not work in visual studio,
Value = (from o in DB.Tags
from p in DB.table_tags
where o.Prefix != null && o.Prefix == p.C_NAME && o.Facility == 11
orderby p.id descending
select new
{
FType=o.TagType,
Name = o.TagsName,
Value = p.C_VALUE,
Time = p.C_TIMESTAMP
}).Take(Tags.Count(h => h.Facility == y.FacilityID))
and it gives an error.
I guess the part with .Take() doesn't work because it's linq to EF.
error:
Limit must be a DbConstantExpression or a Db Parameter Reference Expression. Parametre name: count]
error image
thank you have a good day
Not sure but I will just throw it in. If you are talking about linq to ef/sql, it is possible they dont know a thing about C#. If take() would be the problem try to get the select result local first by doing .tolist(). Afterwards use your take funtion.
.ToList().Take(Tags.Count(h => h.Facility == y.FacilityID))

How to compare IEnumerable<string> for null in Linq query

For the following query:
var result = from sch in schemeDashboard
join exp in Expenditure on sch.schemeId equals exp.SchemeCode
into SchExpGroup
where sch.SectorDepartmentId == selectedDepartmentId &&
sch.YearCode == StateManager.CurrentYear
orderby sch.ADPId
select new
{
ModifiedAmounts = SchExpGroup.Select(a => a.ModifiedAmounts),
ProjectName = sch.schemeName,
ADPNo = sch.ADPId,
Allocation = sch.CurrentAllocation,
Expenditures = from expend in SchExpGroup
where expend.YearCode == StateManager.CurrentYear &&
expend.DepartmentId == selectedDepartmentId &&
InvStatus.Contains(expend.Status)
orderby expend.ADPId
group expend by expend.InvoiceId
};
I want to filter the above query on a condition so that result gives only those records where "ModifiedAmounts" are not null. I have tried as follow:
if (rbList2.SelectedIndex == 6)
{
result = result.Where(a => a.ModifiedAmounts != null));
}
but this gives error as:
Cannot compare elements of type
'System.Collections.Generic.IEnumerable`1'. Only primitive types,
enumeration types and entity types are supported.
Any suggestions as I am lost as how to rephrase the filtered query.
I think the problem is that ModifiedAmounts will never be null. Select will return an empty list. Unless SchExpGroup is null in which case you will get a null reference exception.
Try changing your code to
result = result.Where(a => a.ModifiedAmounts.Any());
if (rbList2.SelectedIndex == 6)
{
result = result.Where(a => a.!ModifiedAmounts.Any());
}

Linq statements, multiple where clauses

I have this linq statement I just wrote:
Location loc = db.Locations.Where(l => l.name == name).Where(l => l.type == "SERV").FirstOrDefault();
I am wondering if this is how you do select from where and ... or if there is a better way to do this
I am trying to do select from locations name where the name is the name passed in and the type is the type passed in, get me the first location that matches this.
You do not need to chain Wheres - you can use && instead. Moreover, since FirstOrDefault takes a condition, you can move the entire clause inside the call, like this:
Location loc = db
.Locations
.FirstOrDefault(l => l.name == name && l.type == "SERV");
What you are doing will work just fine, but you can also just do this:
Location loc = db.Locations.Where(l => l.name == name && l.type == "SERV").FirstOrDefault();
UPDATE:
Since this is apparently going against a database object I was curious what the underlying SQL would look like in each case - my guess is they would be the same.
I used a ToTraceString() extension to view the SQL and just as expected, they are the same.

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();

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