I have this code:
// GET: Teachers/Edit/5
public ActionResult Edit(Guid? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
string uname = User.Identity.GetUserId();
Teachers teachers = db.teachers.Find(id);
if (teachers == null)
{
return HttpNotFound();
}
ViewBag.GroupID = new SelectList(db.groups, "GroupID", "GroupName", teachers.GroupID);
return View(teachers);
}
I am attempting to filter my returned results by id (which is my DB key) but also by the user name which is also stored into the database but not as a key.
I'm not sure of the syntax, but I am pretty sure find is not the way to go.
You can use SingleOrDefault:
db.teachers.SingleOrDefault(x => x.ID == id && x.UserName == username);
It returns a single, specific element of a sequence, or a default value if that element is not found. It will throw exception if there is more than one element in the result.
Additionally, you can also use Single(), First(), FirstOrDefault() in such places. Here is the differences between them:
First() - throws exception if empty or not found, does not throw if duplicate
FirstOrDefault() - returns default if empty or not found, does not throw if duplicate
Single() - throws exception if empty or not found, throws if duplicate exists
SingleOrDefault() - returns default if empty or not found, throws if duplicate exists
P.S: You haven't stated your column names. So, I have just guessed their names. You can change them as you wish.
Related
This is my code to find string in my UserTable.
var PhoneExists = _db.UserTable.Where(u => u.PhoneNumber == Input.PhoneNumber);
and this is my if code:
if (PhoneExists != null)
{
ErrorAlert("number found.");
return Page();
}
but every time the if condition is true.
It returns true as PhoneExists is not null, but it returns with IQueryable value.
You need to materialize the query to return the result queried from the database.
You may look for .Any() to find whether there is any record with the respective PhoneNumber existed.
bool PhoneExists = _db.UserTable.Any(u => u.PhoneNumber == Input.PhoneNumber);
if (PhoneExists)
{
...
}
Where will always return a non-null enumerable, and it's empty if there are no matches. You have to check its contents. If you expect the phone numbers to be unique, you could use FirstOrDefault or SingleOrDefault to return either a string, or null. The latter will, however, throw if there is more than one match.
You can use Contains here.
Sample code:
var PhoneExists = _db.UserTable.Where(u => u.PhoneNumber.Contains(Input.PhoneNumber)).FirstOrDefault();
In your if code:
if (PhoneExists != null && PhoneExist.Count()== 0)
{
ErrorAlert("number found.");
return Page();
}
You can use Exists instead of Where like this :
if (_db.UserTable.Exists(u => u.PhoneNumber == Input.PhoneNumber))
{
//Do Something
}
About exist checkout https://learn.microsoft.com/tr-tr/dotnet/api/system.collections.generic.list-1.exists?view=net-6.0
You can use FirstOrDefault()
var PhoneExists = _db.UserTable.Where(u => u.PhoneNumber == Input.PhoneNumber).FirstOrDefault();
Assuming I have a LINQ query as such ...
var selectedUser = myDb.Users.Where<User>(u => u.Email == email).Single<User>();
What is the best way to see if I received a result back? Do I just check if selectedUser != null
if (selectedUser != null)
{
// OK, not null so go ahead and do stuff
}
Single() will throw an exception if there are no matches.
SingleOrDefault() will return a single element, or a default value. However it will throw exception if there are more than one element in the sequence.
If you are ok with just taking the first element if there happens to be more than use FirstOrDefault() for this:
var selectedUser = myDb.Users.FirstOrDefault(u => u.Email == email);
Then just check if it is null like normal:
if (selectedUser != null)
{
// OK, not null so go ahead and do stuff
}
Side Note In either case you shouldn't need your explicit <T> definitions. Also the Where() clause is redundant, you can pass your lambda in FirstOrDefault(), Single(), SingleOrDefault(), etc.
.Single will throw an exception if there isn't a matching item. Instead use SingleOrDefault and check for null.
I'm working on an application with mvc5 and want that when I load a page, it will check if datetime of data equals DateTime.Today in table, and if so, that it will then set a boolean value to true.
public ActionResult Index()
{
Detail v = db.Details.Single(emp => emp.DateExpired.Value.Equals( DateTime.Today));
v.Expire = true;
db.SaveChanges();
return View();
}
It gives me this error
because there was more than one for which this date equals DateTime.Today,
What can be done to take this possibility into account?
public ActionResult Index()
{
foreach (var r in db.Details.Where(emp => emp.DateExpired.HasValue && emp.DateExpired.Value == DateTime.Today))
{
r.Expire = true;
}
db.SaveChanges();
return View();
}
Single() works where it expects only one result to be returned and will throw an error when it finds a match. From msdn :
Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence.
For your case you should use First() or FirstOrDefault()
FirstOrDefault will return a null when no match is found.
Edit :
If you want to apply the logic on all matches you should use Where()
I have the line below but still get an exception "Sequence contains more than one element"
Details rd = this.db.Details.SingleOrDefault(x => x.TId == Id && x.TypeId == TypeId);
I was hoping that SingleOrDefault would avoid the exception.
SingleOrDefault returns a SINGLE element or null if no element is found. If 2 elements are found in your Enumerable then it throws the exception you are seeing. Just like Highlander... with Single - there can be only one.
FirstOrDefault returns the FIRST element it finds or null if no element is found. so if there are 2 elements that match your predicate the second one is ignored.
Assuming you don't care if there are multiple matches and you only want the first one or null if no match is found... then you probably want the following...
Details rd = this.db.Details
.FirstOrDefault(x => x.TId == Id && x.TypeId == TypeId);
Note that both of these methods only return one element they only differ in what they do after they find a match. First stops looking at that point and returns what it found, Single keeps checking the rest of the list to make sure there are no more matches. The OrDefault part determines what it returns if no match is found. SingleOrDefault or FirstOrDefault returns null if no value is found but if you just use Single or First then it MUST find one match or it will throw an exception.
EDIT: Good point Steve
Since First returns the first element you may need to use an OrderBy in order to make sure the element you want is indeed first. For instance... suppose your object had an UpdateDate property and you wanted the object with the most recent UpdateDate...
Details rd = this.db.Details
.OrderByDescending(x => x.UpdateDate)
.FirstOrDefault(x => x.TId == Id && x.TypeId == TypeId);
In case you are having a list, convert the list to IEnumerable list, then you can make use of FirstOrDefault method
IEnumerable<BuyOnlineSearchdetails> details = new List<BuyOnlineSearchdetails>();
var FirstRow = details.FirstOrDefault();
string Count = "0";
if (FirstRow != null)
{
Count = FirstRow.TotalCount.ToString();
}
else
{
Count = "0";
}
You have to use FirstOrDefault() instead of SingleOrDefault().
SingleOrDefault throws an exception if more than one element exists where as FirstOrDefault not.
How do you return a specific type in a Linq query? I know you can use ToList() to return a list of specific objects but how do you return a non list?
MyObj x = from x in list where x.id == 99 select x;
MyObj x = (from x in list where x.id == 99 select x).Single();
if you expect that the id might not exist, then you could use SingleOrDefault to return the default value for the type (probably null in this case).
You could, of course, use First() but I'd be wary, as this could hide errors if you expect to only have one item returned.
MyObj x = list.FirstOrDefault(i=>i.id == 99);
Alternative IEnumerable methods you can use to return a single item:
list.Single(i=>i.id == 99): throws an exception if no matches are found or multiple matches are found.
list.SingleOrDefault(i=>i.id == 99): returns null if no matches are found, throws an exception if multiple matches are found.
list.First(i=>i.id == 99): throws an exception if no matches are found. If multiple matches are found, returns the first item in the list.
list.FirstOrDefault(i=>i.id == 99): returns null if no matches are found. If multiple matches are found, returns the first item in the list.
MyObj x = list.Where(x => x.id == 99).FirstOrDefault();