Error at c# linq comparison - c#

I have this linq and on my form there are textboxes which shows the databindings in text boxes of the selected item from the listbox(datasource from database).
var j = (from s in db.Movies where s.Movietitle == listbox1.SelectedValue select s).First();
I must compare the movie title to the selected item of the listbox,they must be equal but my code can't continue to run because of the error:Warning 1 Possible unintended reference comparison; to get a value comparison, cast the right hand side to type 'string'
I casted (string) before the listbox but still no change. What can be the problem?

Cast listbox1.SelectedValue as sting and use FirstOrDefault(), since query may return no results.
Use s.Movietitle.ToString(), to avoid "Possible unintended reference comparison". The issue is that s.MovieTitle is reference type. If, for example it is of type object, the comparison operator "==" selected is comparing two objects...by reference as you may guess.

Related

LINQ - Using FirstOrDefault or DefaultIfEmpty?

I'm getting confused about how to use FirstOrDefault or DefaultIfEmpty.
The snippet below may be empty, but if it's not, I definitely want the first one.
var vThr = _context.PostThrs.FirstOrDefault(m =>
m.ThrZero == zero
&& m.ThrText.Substring(0,8) == "SERVICE-");
If it is empty, I would like the result to be "Empty". How would I do that?
I've taken some stabs at it, but I'm not sure that it's helpful to share.
EDIT: After posting, I realized that the question doesn't really work as you cannot insert a single string into the result.
Summarize between:
.FirstOrDefault()
.DefaultIfEmpty()
Query with the result of the first item that fulfills.
Query with the result of IEnumerable. Use to initialize a default item if the sequence is empty.
- If there is item(s) fulfilled, return the first T item.
If there is item(s) fulfilled, return at least one or more T items as IEnumerable<T>.
- If not, returns default.
- If not, the defaultValue parameter is used to initialize into IEnumerable<T>. Returns an IEnumerable<T> with a single item (Count = 1).
So, based on your requirement, you are looking for .FirstOrDefault() to check the returned result is null and perform the following implementation.
Didn't cover the part that you want to assign an "Empty" string to the variable when null and you found out that it is not feasible to do as the variable is T which will conflict with the type.
References
.FirstOrDefault()
.DefaultIfEmpty()
Use FirstOrDefault() it will find first matched by condition element but if not will return just null

LINQ issue with Equals statement

I'm getting an error for the following:
var answerList = (from answer in db.QuestionAnswers
where answer.tLoginID.Equals(tId) && answer.pLoginID.Equals(pId)
&& answer.Submitted.Equals(submittedVal)
select answer).ToList();
The error is:
Unable to create a constant value of type 'System.Object'. Only
primitive types or enumeration types are supported in this context.
However, when I change it to:
var answerList = (from answer in db.QuestionAnswers
where answer.tLoginID.Equals(tId) && answer.pLoginID.Equals(pId)
select answer).ToList();
Then I do this:
answerList.Where(x => x.Submitted.Equals(submittedVal));
It works... What am I missing? To me these statements are doing the same thing. But I'm not sure why it is working like this.
UPDATE:
I figured out after looking at the link that #SergeyLitvinov provided about .Equals that the column I was checking Submitted was actually a Boolean instead of an Integer once I made the types the same my statements worked. Although I did change it from .Equals to ==.
The error is from the LINQ to Entities query provider which is attempting to transform your query expression into a SQL statement. Your second example enumerates your LINQ to Entities query prior to testing for Submitted.Equals(submittedVal), which mean you're using standard LINQ to Objects in local memory (i.e. it is not converted to SQL).

Access database with LINQ, datatype conflict

I am trying to access data from my database with LINQ but I am running into a data type error.
Here is my code:
public static String GetCheckIfCsIsRunning()
{
using (Entities db = new Entities())
{
Stringl status = (from stat in db.Messenger_Settings
where stat.Id == 1
select stat.SettingValue);
return status;
}
}
I am currently getting an error at
where stat.Id == 1
saying
Cannot implicitly convert type 'int' to 'bool'
I am trying to select from my table the ID of the row but the line of code is saying the Id is type bool? Perhaps the 'status' variable of the code creates 'stat' into a bool type. But how would I select the row according to Id?
my table structure is
ID(int) | Name(varchar) | SettingValue(varchar)
EDIT
I forgot to add an extra '=' ('=' --> '==')
EDIT-2
replaced int's with bool's new error occurs
- data I want to access is varchar (select stat.SettingValue)
Cannot implicitly convert type 'System.LINQ.IQueryable,string.' to 'string'
You're mistakenly using an assignment operator (=) in place of an equality operator (==).
Your line
where stat.Id = 1
actually assigns 1 to stat.ID, not what you want at all; then, the assignment returns the value assigned, in this case 1. Since C# won't implicitly convert an int to bool, you get the error you see. What you want to do is instead use ==, the equality operator, which will do what you expect: check if the value of stat.Id is 1 and return true or false.
Also, for future reference, you can avoid accidental assignment errors like this by using a different programming idiom: put the constant first, i.e.
1 = stat.Id
While you'd still get an error either way here, in other cases where you do an accidental assignment, or in languages that will implicitly convert int to bool (which would be a runtime error that's hard to track down), you'll instead get an error, since you can't assign a value to a numeric literal like 1.
Per your edit, LINQ always returns a "lazy-loaded" query. As soon as you try to access any elements in that query, it enumerates it. An IQueryable is the object representation of that query. Since we know that the query represents a sequence of strings (0 or more), we can call one of a few methods against IQueryable<string> to get at the results:
.First() will return the first element in the sequence, and throw if the sequence has no elements.
.FirstOrDefault() will return the first element in the sequence, or a default value if the sequence contains no elements.
.Single() will return the element if there is only one element in the sequence, and throw otherwise (if there are zero or more than one element).
.SingleOrDefault() will return the element if there is only one element in the sequence, a default value if there are no elements, or throw if there are more than one.
Which one to choose depends on your database schema as well as your application's desired behavior. If you know there will only ever be one and exactly one value for a setting, use .Single(), so that you can error out and detect if you get several results. If there might be a value for a setting (or it might not be defined), use .SingleOrDefault(). And if a setting could have several values in the table, use .First() or .FirstOrDefault().
In any case, what you'll get is either a string or a runtime exception in the case of unexpected results.
= is an assignment operator.
You want to compare two values using the == comparison operator.
where stat.Id = 1 needs to be where stat.Id == 1
You're attempting to set the value rather than doing a comparison.
I can see two issues here.
First of all you are trying to pass a string (varchar) to an int.
Second the LINQ you have will produce something like IEnumerable or IQueryable which won't be able to go to an int.
You should probably consider getting First, FirstOrDefault, Sinle, SingleOrDefault

"Value Cannot Be Null" when using LINQ to SQL to Group By and Sum results from a WCF Service request

I'm trying to use LINQ to SQL to sum a row in a a resultset returned from a WCF service. I'm able to use LINQ for basic selects, for order by, for filtering, etc. So far so good.
But when I try to Group By / Sum, I get an error message "Value Cannot Be Null" when trying to Take(5) from the query below. (results is non-null and has 1000+s of items, but the query is null when we try to return it:)
EDIT: I've removed the invalid cast as mentioned in the answer below, instead selecting the aggregate results into a custom class written to order. Now the page runs without error -- but the group by / sum doesn't work.... I just get the top five highest values in the results, not summed by group. Why?
var query = (from h in results
group h by h.Order into hh
select new TopOrders()
{
Order = hh.Key,
Total= hh.Sum(r => r.Price)
}).OrderByDescending(i => i.Total);
return query.Take(5).ToList();
Only possible wrinkle I can point to is that Order is itself a collection (OrderID, OrderName, etc.) and so I've tried grouping explicitly on hh.Key.Order.OrderID and so forth, to no effect.
Anything I'm missing from what you can see? Thanks.
It's probably that r.Price of a few orders is null, so use Sum(r => r.Price ?? 0). But it's a bit of a guess without knowing your data.
Edit
It's so obvious that I overlooked it: you try to cast an IEnumerable of an anonymous type to List<TopOrders>, which is not possible. But the as operator produces null if the cast is not valid. So query itself is null! Either remove the cast, or create TopOrders in stead of anonymous types.

How to use returned linq variable?

I've decided to take a quick look into the LINQ side of things, as opposed to just using a straight up foreach loop, but i'm having some trouble getting it to work, mainly due to datatypes i believe.
So i've got this, so far;
var selectedSiteType = from sites in siteTypeList
where sites.SiteTypeID == temp
select sites;
siteTypeList is a list of SiteTypes. I'm trying to find a particular one (Which i've denounced with variable "temp".
How do i then use this selected SiteType AS a SiteType? When i try and pass "selectedSiteType" through to another function, like so;
mSiteTypeSub.EditSitetype(selectedSiteType);
note: I tried with providing an index, as if selectedSiteType was a list / Array, but that didnt work either, i get the following error:
Argument 1: cannot convert from
'System.Collections.Generic.IEnumerable<DeviceManager_take_2.SiteType>' to
'DeviceManager_take_2.SiteType'
Am i missing something? perhaps a cast of some kind? Like i said i'm new to this and am struggling to get my head around this. Chances are i've got the whole concept wrong and bingbangbosh i've made a fool of myself!
Cheers in advance.
Use First / FirstOrDefault / Single / SingleOrDefault to get an item of the particular type from the collection.
var value = selectedSiteType.First();
// returns the first item of the collection
var value = selectedSiteType.FirstOrDefault();
// returns the first item of the collection or null if none exists
var value = selectedSiteType.Single();
// returns the only one item of the collection, exception is thrown if more then one exists
var value = selectedSiteType.SingleOrDefault();
// returns the only item from the collection or null, if none exists. If the collection contains more than one item, an exception is thrown.
If your return type is a single:
var selectedSiteType = (from sites in siteTypeList
where sites.SiteTypeID == temp
select sites).SingleOrDefault();
If a list (potentially more than one item):
var selectedSiteType = (from sites in siteTypeList
where sites.SiteTypeID == temp
select sites).ToList();
It's the SingleOrDefault / ToList that you're missing from your query.
Shane,
I'm not going to improve on the previous answers. They were both correct. I am going to try and explain a little bit to you, so that you understand it in the future a bit better.
What happens, when you write a piece of code like:
var selectedSiteType = from sites in siteTypeList
where sites.SiteTypeID == temp
select sites;
you don't put the answer into the var (selectedSiteType), instead, you are creating an expression tree, that is evaluated ONLY when you actually use it (in a foreach, or by calling one of the methods (like .First(), .ToList(), SingleOrDefault(), etc).
The default return type of a from statement, is an IEnumerable<>, but if you call the .First() or .SingleOrDefault() (etc), you will dive into that IEnumerable<> and get a specific item.
I hope this helps you better understand what is going on.
Lemme know if I can add anything or if I got anything wrong.
Cheers,
Max

Categories

Resources