cannot update a row with a new datetime value ef codefirst - c#

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?

Related

Issue with query returning null before I can check for null

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.

Error with LINQ: Sequence contains no elements

Occasionally, my users experience the issue where in the log files I can see this exception is thrown (Sequence contains no elements)
I search around and can see this exception happens when you try to access or use aggregate on an empty list.
I searched through the code around this exception (too bad no stacktrace was logged), and the only "potential" culprit is the below lines (that use either Fist(), Last(), Single() or any Aggregate). However I can't understand why and not able reproduce on my local. Please help to advise.
if (data.Any())
return data.OrderByDescending(d => d.UpdatedTime).First().UpdatedTime;
Here, data is a List<MyObject> and MyObject has DateTime property called UpdatedTime
===== More surrounding code =====
This is where I got the unhandled exception in the log. GetRecentUpdates method has its own try catch block, so ruled out.
public ActionResult GetUpdatedTime(long lastUpdated) {
var data = dataAccess.GetRecentUpdates(lastUpdated);
var html = htmlBuilder.Build(data);
return Content(html);
}
public List<MyObject> GetRecentUpdates(long lastUpdatedInTicks) {
var list = _cache.GetRecentRequests(_userCache.UserId);
if (list != null) {
var lastUpdated = new DateTime(lastUpdatedInTicks);
list = list.Where(l => l!=null && l.UpdatedTime > lastUpdated).ToList();
}
return list ?? new List<MyObject>();
}
public List<MyObject> GetRecentRequests(string userId) {
List<MyObject> requests = null;
try {
// simplied but the idea stays
requests = dictionary.Get(userId);
commonRequests = dictionary.Get("common");
if (requests != null) {
if (commonRequests != null)
requests = requests.Union(commonRequests).ToList();
} else {
request = commonRequests;
}
if (requests != null) {
requests = requests.OrderByDescending(r => r.CreatedDateTime).ToList();
}
catch (Exception ex) {
// log the exception (handled)
}
return requests;
}
public string Build(List<MyObject> data) {
var lastUpdated = DateTime.MinValue;
if (data.Any())
lastUpdated = data.OrderByDescending(d => d.UpdatedTime).First().UpdatedTime;
return String.Format("<tr style=\"display:none\"><td><div Id='MetaInfo' data-lastUpdated='{0}' /></td></tr>", lastUpdated.Ticks);
}
The javascript calls GetUpdatedTime every 10s. Ussually everything goes fine, but every once in awhile, this exception is thrown. Once it's thrown, it keeps being thrown every 10s until the user refreshes the page.
Update:
Another version after some investigate: as you've said, your code is running in multhithreading environment, and the data object could be accessed by two or more threads. As it's a reference type variable, the reference of it can be modified. So, consider such situation:
First thread enters the Build method and checking the condition:
if (data.Any())
and the data isn't empty at this moment, so it enters the true block. Right exactly in this time another one thread enters the Build method, but on that moment the data variable is empty, and all reference for it points to empty List. But the first one thread already into the true block:
lastUpdated = data.OrderByDescending(d => d.UpdatedTime).First().UpdatedTime;
And it fails with you exception. And now good news: you can fix it in many ways:
First of all, check the creating data logic. May be, it is a static or shared variable, or object it being populated from, is a static or shared variable, and you have race condition for this resource. You may change the logic of it's creation or wrap it into a some synchronizing primitive so the only one thread can Build at the same time (but this can affect the performance of your program).
Change the logic of GetRecentRequests - can't say for sure, but I think that the situation is something like this: commonRequests are empty all the time, and for the first thread dictionary got some data, but has no data for second thread, and data object is being overridden and is empty. Way to debug it: add Barrier primitive to your program during test run, and wait for 10-15 threads being awaiting for the barrier. After that they'll start simultaneously build your data and error will happen with high probability (do not insert breakpoints - they'll sychronize your threads).
Make a local copy of data object, something like this:
var localData = data.Select(d => d).ToList();
Hope this helps.
Your code is checking, if some data is available, and after that filters the data by date. As you are using the LINQ extension methods, I think that data is an IEnumerable object, not the List, so, when you are calling Any() method, it's being enumerated, and after that, you are calling the First() method, which is enumerating it too.
So, if your data is being a result of some yeild return method, it's being enumerated once, and on second time there is no data there, and sequence is empty.
Consider to change your code to work with data as a List or Array, or use the FirstOrDefault method to have a null object if there is no data, like this:
//var dataList = data.OrderByDescending(d => d.UpdatedTime).ToList();
if (data.Count > 0)
return dataList[0].UpdatedTime;
or
var firstElement = data.OrderByDescending(d => d.UpdatedTime).FirstOrDefault();
return firstElement != null ? firstElement.UpdatedTime : DateTime.MinValue;
Try FirstOrDefault() method.
var lastUpdated = DateTime.MinValue;
var first = data.OrderByDescending(d => d.UpdatedTime).FirstOrDefault();
if (first != null)
{
lastUpdated = first.UpdatedTime;
}
I don't know what MyObject definition is like. But I am guessing the
UpdatedTime field is DateTime?. If so, it happen at last method, when:
lastUpdated = data.OrderByDescending(d => d.UpdatedTime).First().UpdatedTime;
return String.Format("<tr style=\"display:none\"><td><div Id='MetaInfo' data-lastUpdated='{0}' /></td></tr>", lastUpdated.Ticks);
Where the UpdatedTime is null, and lastUpdated.Ticks throw NullReferenceException.
Your code checks first if any element of data collection satisfies a predicate with data.Any(). Since there's no predicate, this call is equivalent to tell you if your data collection has elements or not.
For this reason, I don't think that the line
return data.OrderByDescending(d => d.UpdatedTime).First().UpdatedTime;
is the real problem, because an exception with the message Sequence contains no elements is thrown when some operation is performed in an empty collection. Since there're elements within data (and then data.Any() returns true), the exception is about another line in your code.
You should add more logging to your application, in order to get the full stacktrace of the exception and understand better which line is causing the error.

Entity Framework - Handling a join with no records from join table

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!

LINQ in EF fails when searching for null values?

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

C# lambda extract a single row string value

Want to extract the text value from a lookup table's column in a db. EL is the entity for my db. Current code :
var QTypes = EL.ElogQueryType.Where<ElogQueryType>( eqt=> eqt.ID == queryTypeID);
string qType = QTypes.First().QueryType;
I get a list when I just pull .Select(... so something is wrong.
You should be able to just do if you know you will be just getting one item:
var QTypes = EL.ElogQueryType.Where(eqt=> eqt.ID == queryTypeID).Single().QueryType;
If you are not sure if you will get one or nothing use SingleOrDefault().
If you just want the first since you are expecting many records do:
var QTypes = EL.ElogQueryType.First(eqt=> eqt.ID == queryTypeID).QueryType;
Same applies if you don't know if you will get anything, use FirstOrDefault.
It's not clear what's wrong, as your current query should give you what you're after. However, you can also use the overload of First which takes a predicate:
string qType = EL.ElogQueryType.First(eqt => eqt.ID == queryTypeID)
.QueryType;
You say you "get a list when [you] pull .Select(" but it's not really clear what you mean. You haven't said what's wrong with the code you've already specified.
(As Kelsey says, there are alternatives to First: FirstOrDefault, SingleOrDefault, Single and even Last should you wish.)

Categories