LINQ - Sorting by using OrderBy on a nullable field - linq

I'm trying to sort a collection of type Enumerable<DataRow> by using LINQ's OrderBy method on a nullable Int32 field. Because some of the values of this field are null, Visual studio throws a System.ArgumentException with message 'Object must be of type Int32.' Here is the problematic line of code:
collection1 = collection1.OrderBy(row => row["Column1"]);
where Column1 is the nullable Int32 field and the variable collection1 is declared as:
IEnumerable<DataRow> collection1;
Is there a way to rewrite the above line so that it ignores the nulls?

You could use the ternary conditional operator:
collection1 = collection1.OrderBy(row =>
row["Column1"] != null ? row["Column1"] : low_priority_indicator);
Where low_priority_indicator is an integer representing a standard, low-order (in respect to your priorities) value. Otherwise you could filter out the null values before ordering, if you want to exclude entirely from the resulting collection.

Try this:
collection1.OrderBy(row => row.Field<int?>("Column1"));

Try the following:
collection1 = collection1.Where(row => row["Column1"] != null).
OrderBy(row => row["Column1"]);

this will ignore the values - try this:
collection1 = collection1
.Where(c => c["Column1"].HasValue)
.OrderBy(row => row["Column1"]);

Related

linq Command not getting the answer for DB

i have a table(UserQuestions) in my DB(WebSiteUsers) which contains QuestionID field as a Primary key and QuestionContext field which holds the Questions that are asked as its value.
Now i want to have a textBox that show me the QuestionContext Value by getting QuestionID.
I used these linq commands and none of them bring me the correct answer :
string Questioncontext = new WebSiteUsersEntities().UserQuestions.Where(p => p.QuestiuonID.ToString() == QuestionID).Select(p => new { p.QuestionContext}).ToString();
string Questionx = (from q in new WebSiteUsersEntities().UserQuestions where q.QuestiuonID.ToString() == QuestionID select q.QuestionContext).ToString();
QuestionCntxt.Text = Questionx;
the outcome is like this :
SELECT
[Extent1].[QuestionContext] AS [QuestionContext]
FROM [dbo].[UserQuestion] AS [Extent1]
WHERE CAST( [Extent1].[QuestiuonID] AS nvarchar(max)) = #p__linq__0
I guess your QuestionID variable is of type string, while the database column is of type int.
So rather than using
q.QuestiuonID.ToString() == QuestionID
criteria inside the query, convert the variable to int and use that as criteria.
Also ToString just gives you the SQL query text, not the result. Use ToList if you expect more than one result or FirstOrDefault if you expect zero or one results:
var questionID = int.Parse(QuestionID);
string Questioncontext = new WebSiteUsersEntities().UserQuestions
.Where(p => p.QuestiuonID == questionID)
.Select(p => p.QuestionContext)
.FirstOrDefault();
Note that I also changed the select to return directly QuestionContext string rather than anonymous object having QuestionContext property.

Why is this LINQ to EF query not working?

I have a problem with the following method:
public IQueryable<Customer> ListCustomers(int? parentId)
{
Debug.Assert(parentId == null);
//var list = _customerRepository.List().Where(c => c.ParentId == null);
var list = _customerRepository.List().Where(c => c.ParentId == parentId);
return list;
}
I have one Customer in my DB with a ParentId of null. When I call the method with ListCustomers(null), list is empty for the return statement. If I swap the commented out line in and query with a hard-coded null, then list contains my one customer.
What could cause this difference between these two queries? Why is the one with c.ParentId == parentId not returning anything?
Becouse the Nullable type the linq provider will not generate the proper IS NULL check. See this answer for further information: https://stackoverflow.com/a/785501/1195510
EF translates your query with int? to something like this:
DECLARE #parentId Int = null
SELECT ... WHERE ParentId = #parentId
When this is executed on the database, it doesn't do what you expect because in SQL [column] = NULL is always false.
I agree EF could handle this better, but as a workaround, you can write something like this:
.Where( c => !parentId.HasValue
? !c.ParentId.HasValue
: c.ParentId.Value == parentId.Value
)
EF will then generate a ( somewhat verbose ) SQL statement with the correct IS NULL predicates.
with nullable types you have to use it like this:
.Where(c=> object.Equals(c.ParentId, parentId))

Why is the sum of an empty set null?

If I do:
int updateGamePlays = db.tblArcadeGames.Where(c => c.ParentGameID == GameID).Sum(c => c.Plays);
If no records are returned in this query it throws:
System.InvalidOperationException: The null value cannot be assigned to
a member with type System.Int32 which is a non-nullable value type.
The only way to get it to return 0 is by doing:
int updateGamePlays = db.tblArcadeGames.Where(c => c.ParentGameID == GameID).Sum(c => (int?)c.Plays) ?? 0;
In the database c.Plays is a non-nullable int.
In set theory the sum of an empty set should equal 0 (ref). How comes in Linq-to-SQL did they decide to make it return null?
According to a source at Microsoft, Sum() on an empty set is null because of the way it works in SQL:
when the table is empty i´m getting this exception: InvalidOperationException
In SQL, Sum() aggregate operator returns null for an empty set. So this is as designed.
Another alternative is to add a 0 to the set to make sure there's always at least one value.
int updateGamePlays = db.tblArcadeGames.Where(c => c.ParentGameID == GameID)
.Select(c => c.Plays)
.Concat(new [] { 0 })
.Sum();
You can use the more general Aggregate method with a seed of zero:
int updateGamePlays = db.tblArcadeGames
.Where(c => c.ParentGameID == GameID)
.Aggregate(0, (a, c) => a + c.Plays);
This does not require using nullable types.

LINQ query - null date

Ive a simple linq query to return records with a null date field,
just want to check the synatx of the "where" line is ok
var query2 = from cs in db.tblCases
where cs.date_closed == null
etc, etc,
thanks again
DD
I would be careful with using null, I have seen issues with linq not generating the correct sytnax (ex IS NULL vs ==null)
I would recommend
var query2 = from cs in db.tblCases where !cs.date_closed.HasValue etc, etc,
Assuming your date_closed property is of a nullable type, e.g. Nullable<DateTime> aka DateTime?, that should be fine.

Null value cannot be assigned - LINQ query question

I have the following LINQ query:
DataClassesDataContext dc = new DataClassesDataContext();
var query = from contact in dc.Contacts
select new
{
ContactId = contact.ContactId,
LastName = contact.LastName,
FirstName = contact.FirstName,
Addresses = contact.Addresses,
Phones = contact.Phones,
DOB = contact.BirthDate,
LastNote = contact.Notes.Max(n => n.Created), //this line causes the error
Status = contact.ContactStatus.ContactStatusName,
EmailAddress = contact.Emails
};
The line where I get the maximum created date for the notes collection causes the following exception to be thrown:
Exception: The null value cannot be assigned to a
member with type System.DateTime which
is a non-nullable value type.
How do I write the query to allow null values into the LastNote field? The DOB field is defined as DateTime? and has not problem handling nulls.
Think I figured it out.
If I cast the maximum note value to a nullable DateTime it seems to eliminate the exception. The following change worked for me:
LastNote = (Nullable<DateTime>)contact.Notes.Max(n => n.Created)
As others have pointed out, it can also be written using the shorthand notation for a nullable DateTime as follows:
LastNote = (DateTime?) contact.Notes.Max(n => n.Created)
Rewrite that line as:
LastNote = (DateTime?) contact.Notes.Max(n => n.Created),
LastNote = contact.Notes.Max(n => (DateTime?)n.Created)
Couldn't find this on the net so i hope this helps others.
In VB is something like:
LastNote = CType(contact.Notes.Max(n => n.Created), Global.System.Nullable(Of Date))
I think...
You could do that, or you could alter your database schema so that the column 'Created' does not allow nulls.
The scenario is arising because one of the rows comes back with a null value for Created.
If the db didn't allow nulls, the scenario would never occur.

Resources