I have the following code.
//I pick the first story where its StartSegment is not null.
var story = container.StorySet.FirstOrDefault(s => s.StartSegment != null);
if (story != null)
{
//the following assert fails because story.StartSegment is null.
Assert.IsNotNull(story.StartSegment,
"The target story of this homework has no start segment.");
}
This unit-test fails, because story.StartSegment is in fact null, but given the FirstOrDefault lambda expression which explicitly searches for stories where the start segment isn't null, I don't think this makes any sense.
Can anyone help me?
it's lazy/eager load ploblem.
in fact Story.StartSegment is not null.
but you didn't include it (by eager load). try this..
var story = container.StorySet
.Include("StartSegment ")
.FirstOrDefault(s => s.StartSegment != null);
assume that your entitie relation like this..
StorySet (many) ----- (0 or 1) StartSegment
StartSegment defined as "NavigationProperty" of StorySet. and your generated query look like
SELECT * FROM StorySet WHERE StorySet.StartSegmentId is not null
this query return some existing entity. but by default EF will not create instant of Navigation Property until you explicitly tell it to .Include("StartSegment")
Try the following code:
var story = container.StorySet.Where(s => s.StartSegment != null).FirstOrDefault();
I think it's DB bool logic related issue. In SQL this is not true: someNullValue = NULL. Instead you should use someNullValue IS NULL. Probably EF doesn't care about correct null comparison in this case, so it just returns the first element, which might have null StartSegment. Check the query that it is issued to the database. It should have IS NULL predicate, not something like = NULL
Related
I am confused. I have two statements that are the same and one works and the other receives the error - value cannot be null. r nparameter name source. From what I read I am receiving the error because something is null in my linq expression. However from what I can tell nothing is null.
The first if statement works. When a person selects 'Select' from a list of Burn Project a list of BurnPiles is displayed below the BurnProject list. (this works). Then when a person selects 'Select' from the list of BurnPiles a list of RequestedBurns is display below it. This gives me the null error. At one time it did work now it doesn't.
I am at a loss of what went wrong. I do know the RequestedBurn Table starts at record #2 but that shouldn't have anything to do with it. The BurnPile records that I have been using have associated RequestedBurns.
//when 'Select' is chosen from the list of burn projects the list of burn piles
//associated with that specific burn project is display below it.
if (burnerID != null)
{
ViewBag.BurnerID = burnerID.Value;
viewModel.BurnPiles = viewModel.BurnProjects.Where(
b => b.BurnerID == burnerID.Value).Single().BurnPiles;
}
//when 'Select' is chosen from the list of burn piles the list of requested
//burns associated with that specific burn pile is displayed below it.
if (burnPileID != null)
{
ViewBag.BurnPilesID = burnPileID.Value;
viewModel.RequestedBurns = viewModel.BurnPiles.Where(
x => x.BurnPilesID == burnPileID).Single().RequestedBurns;
}
If you look at documentation for Where or Single, you would see that source is the name of the parameter that represents your collection. So, it looks like you are trying to call a method on null reference, which would be the case if viewModel.BurnProjects = null or viewModel.BurnPiles = null.
viewModel.BurnPiles = viewModel.BurnProjects.Where(
b => b.BurnerID == burnerID.Value).Single().BurnPiles;
could be setting viewModel.BurnPiles to null.
or
viewModel.BurnPiles.Where(
x => x.BurnPilesID == burnPileID).Single()
is returning nothing so when you try and access RequestedBurns then it throws an exception.
SingleOrDefault also has an overload where you can simplify the expression a bit more. You can also combine it with the null conditional operator (if using at least C# 6).
if (burnerID != null)
{
ViewBag.BurnerID = burnerID.Value;
viewModel.BurnPiles = viewModel.BurnProjects.SingleOrDefault(b => b.BurnerID == burnerID.Value)?.BurnPiles;
}
For an invite function, I have a screen with a single field on it that lets users enter a code they've been given elsewhere. I then check in the controller to see which record is associated to this code. But my issue is with the controller blowing up if the code is not the first type is checks for (type 1 or type 2). So here what I believe it should be like(this doesn't work), although I realize the sloppiness I'm just new to c#.
Record rec = db.Records.Where(u = u.Code1).First();
If (rec != null)
{
Other code...
Exit controller
}
Record rec2 = db.Records.Where(u = u.Code2).First();
If (rec2 != null)
{
Other code...
Exit controller
}
Return to view - codes are invalid.
I've attempted other versions where I put the object check within the if statement but there didn't work either. Any ideas?
Use FirstOrDefault not First. First throws an exception if the collection is empty, FirstOrDefault returns default(T) if the collection is empty.
And actually, there are overloads of First and FirstOrDefault that take a condition parameter, so you don't need to call Where
ex:
var x = numbers.FirstOrDefault(n => n % 2 == 1);
This will return the first odd number in the collection, or 0 if there are none that meet the condition (or none at all.)
As explained by the MSDN docs on IEnumerable.First, this method throws an exception if there are no elements in the sequence
The First(IEnumerable) method throws an exception if
source contains no elements. To instead return a default value when
the source sequence is empty, use the FirstOrDefault method
So you should write
Record rec = db.Records.FirstOrDefault(u => u.Code1);
if(rec == null)
{
....
}
Notice that the same condition used in the Where extension could be used directly with FirstOrDefault
By the way, it is unclear what your expression is. The lambda expression (syntax is => ) should return a boolean value so, or your Code1 is a boolean variable or something is wrong in that line
Use db.Records.Where(u => u.Code1).FirstOrDefault();
Check the comparison value (ex. u.code1) if it has this property from the model before binding to the query.
EditThe query is correct, the error I was getting was due to the fact that the logout fx below was called twice, once from html href and another from ajax. The ajax call had the UID while the Html had null, hence exception was thrown -- the html was called later. Thank you for your inputs. Since I am new to stackoverflow, I am not sure how to treat the answers/comments as they are all right.
How do I update a row with a new datetime value?
try
{
var last = (from l in db.loginActivity
where l.UID.Equals(_uid)
orderby l.LastLogin descending
select l).FirstOrDefault();
last.LastLogout = DateTime.Now;
db.Entry(last).State = EntityState.Modified;
db.SaveChanges();
}
When I used the FirstOrDefault() -> error: object ref not set to an instance of an object.
When I used the First() -> error: sequence contains no element.
Well, the database has several records. I have used this snippet somewhere and it works like a charm, only when the updated cells weren't of datetime type.
Any advise?
The error is telling you that no record with a matching UID was found, so therefore last is null. You need to check that it's not null:
var last = ...;
if (last != null) {
last.LastLogout = DateTime.Now;
db.Entry(last).State = EntityState.Modified;
db.SaveChanges();
}
Alternatively, since you're doing this in a try/catch, you could use First instead of FirstOrDefault and just catch the exception First throws when it doesn't find a record.
As for why last is coming back null, set a breakpoint and make sure _uid is what you expect it to be.
Looks like no items satisfy your filter condition: where l.UID.Equals(_uid)
Did you try to remove "where" from the query?
I searched vigorously for an answer to this, but I was unable to find (or understand) a solution. I have a query where I am joining to another table that may or may not have associated records. Here is the query:
var educationUniversity = result.new_educationUniversity.Select(c => new
{ c.majorDegree, c.dateEnd, c.dateStart, c.institutionName,
c.degreeProgramCompletionStatus, c.institutionAddress,
attachmentId = c.attachmentId ?? 0,
fileName = c.new_attachments.fileName ?? "No Attachment"}).ToList();
The first table is "new_educationUniversity" and it holds details of a user's college or university degree. The user may or may not have uploaded an attachment (which is stored in the "new_attachments" table). The attchmentID is the primary key in the "new_attachments" table and a foreign key in the "new_educationUniversity" table. EF sees the relationship.
I am binding the results to a repeater but the code fails on the line above if there is no related attachment. Everything works fine if there is an attachment or if I remove the reference to the fileName.
Above, I am handling if the fileName is NULL (or at least I am trying to), but I suspect my issue is that the record simply doesn't exist, which is different from NULL I guess. I've tried using something like: c.new_attachments.fileName.SingleOrDefault() or DefaultIfEmpty() with no luck.
As an analogy, imagine you have a CUSTOMERS table and an ORDERS table. You want to query the following:
-customer last name
-customer first name
-customer most recent order Id
However, you have registered customers who have never purchased anything. I'm sure I am doing something completely noobish, so any assistance is GREATLY appreciated. Thanks!
So you have a few things going on here:
You can get a null reference exception on your reference to c.new_attachments.fileName. If new_attachments is null, then this will throw an exception. Including the null-coalescing operator (the ??) won't help, because you're trying to access the property of something which can be null.
Unless you're lazy-loading (generally bad), then there's no reason for you to be trying to create a dynamically typed object to send to your repeater. Just pass the result.new_educationUniversity object directly.
What's the solution?
I'd create a partial class to add a new property to your new_educationUniversity class. Add a null-reference-safe property reference to determine the file name of the new_attachments property of new_educationUniversity. Then, bind the repeater to your new property. Something like:
public partial class new_educationUniversity {
public String AttachmentFileName {
get {
if (new_attachments == null)
return "";
else
return new_attachments.fileName;
}
}
}
The following line of code seems to be working.
var educationUniversity = result.new_educationUniversity.Select
(c => new { c.majorDegree, c.dateEnd, c.dateStart, c.institutionName,
c.degreeProgramCompletionStatus, c.institutionAddress, attachmentId = c.attachmentId ?? 0,
fileName = (c.new_attachments == null ? "***NO ATTACHMENT***" : c.new_attachments.fileName)}).ToList();
I don't fully understand what this line means:
fileName = (c.new_attachments == null ? "***NO ATTACHMENT***" : c.new_attachments.fileName)}
I assume it says "if nothing is there replace with the string "NO ATTACHMENT" otherwise use what is in the DB"
Is this acceptable? So far, so good. Thanks!
I'm quite new to LINQ & Entity framework as well as the var keyword in c# so please pardon me if this sounds like a 'newbie' question.
I have problems checking for null values after doing something like this:
var entry = myDB.Entries.Where(e => e.Email == entry.Email);
Even when the email does not exist in the database, entry does not equate to null.
So instead of if (entry == null) i had to do if (entry.Count() < 1) to check for existing Entry before i execute my next batch of statements. Is there any reason why the variable wouldn't be considered null?
In your example, entry will never be null. What you think of as null is in fact an IEnumerable<Entry> with no items.
If you want to check if there is at least one entry with your criteria, you normally do something like:
var entries = myDB.Entries.Where(e => e.Email == entry.Email);
if (entries.Any()) {
// ...
}
If you know that there will be at most one entry, then you can also do:
var entry = myDB.Entries.Where(e => e.Email == entry.Email).SingleOrDefault();
if (entry != null) {
// ...
}
This is closer to what you imagined, but will throw an exception if there is more than one matching entry.
"var" keywords make it possible to achieve any type based on the assignment at runtime, so when you query using "Where" the var entry becomes "IEnumerable" that is returned by Where, that's why you have to check for count.
In VB
Dim entry = myDB.Entries.Where(Function(e) e.Email = entry.Email).SingleOrDefault()
If entry IsNot Nothing Then
' we have a value
else
' we dont have a value
End If