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()
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();
I have a table named dbo.EmployeeType with three records:
PK_EmployeetypeID EmployeeTypeName
1 Project Manager
2 Business Analyst
3 Developer
I have this piece of Linq code:
public static string GetTypeByID(int id)
{
using (ProjectTrackingEntities1 db = new ProjectTrackingEntities1())
{
var type = db.EmployeeTypes.Select(o => new LOOKUPEmployeeType
{
PK_EmployeeTypeID = id,
EmployeeTypeName = o.EmployeeTypeName
});
return type.FirstOrDefault().EmployeeTypeName;
}
}
No matter what id I send to it, it returns Project Manager, and I'm confused as to why.
You need to apply a filter, otherwise you're just returning the first record and hard coding the ID. Try this:
public static string GetTypeByID(int id)
{
using (ProjectTrackingEntities1 db = new ProjectTrackingEntities1())
{
//Here we apply a filter, the lambda here is what creates the WHERE clause
var type = db.EmployeeTypes
.FirstOrDefault(et => et.PK_EmployeeTypeID == id);
if(type != null)
{
return type.EmployeeTypeName;
}
else
{
return "";
}
}
}
Note that using FirstOrDefault means if there are no matches, or multiple matches, type will be null and you will get an empty string returned.
Set a breakpoint on type = ... and inspect it. You have no Where in there so you get all - and Select just makes LOOKUPEmployeeTypes out of all of them.
FirstOrDefault then returns the first of those 3 which is always the ProjManager
Fix:
var type = db
.EmployeeTypes
.Where( o => o.Id == id)
.Select(o => new LOOKUPEmployeeType
{
PK_EmployeeTypeID = id,
EmployeeTypeName = o.EmployeeTypeName
});
In your code you only return the first value. You need to tell EF which value you need to return.
Let us assume you need the value with Id=2. Instead of Select(), use Single(x => x.Id == 2) or First(x => x.Id == 2).
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.
I have a datatable loaded up with some records and I am then pulling a query from another file and want to check if the ID that I pull in this query exists in my datatable.
foreach (var item in records)
{
bool hasit = dt.AsEnumerable().Any(p => p.Field<string>(0) == item.ID);
if (!hasit)
{
//Logic
}
}
I'm using that .Any() function and expecting it to return true if there is an ID in the first field of the datatable that matches the id in the records collection. It continually returns false though, am I missing something? Is there a better way to do this?
I'm using that .Any() function and expecting it to return true if there is an ID in the first field of the datatable that matches the id in the records collection. It continually returns false
When one uses == it compares object references. I recommend you instead use Equals which will just compare the values. Hence change your statement to
dt.AsEnumerable().Any(p => p.Field<string>(0).Equals(item.ID))
Which will achieve what you are expecting.
The method
.Any(p => p.Field(0) == item.ID)
will return true IF ANY element is found. Your posted code specifies that the next thing you do is ask
if (!hasit)
{
//Logic
}
which means if(NOT any has it)... which is producing the incorrect behavior. Change it to:
if (hasit)
{
//Logic
}
and you'll get the desired results.
Edit: kudos to Cuong Le for the observation.
I would try breaking it up to see if I could find the error:
foreach (var item in records)
{
var enumer = dt.AsEnumerable(); // <-- Check this to make sure it has elements
var filtered = enumer.Any(p => p.Field<string>(0) == item.ID); // <- Check to make sure it has elements
}
I'm attempting to write a simple Select method on a class that inherits from IList.
public class RowDataCollection : IList<RowData> {
private List<RowData> rowList;
internal RowDataCollection(List<RowData> data) {
rowList = data;
}
// ...
}
public RowDataCollection Rows;
public RowDataCollection Select(string colName, object value) {
List<RowData> rowList = from item in Rows
where item[colName].Value == value
select item;
return new RowDataCollection(rowList);
}
Some problems I'm having:
First:
VS2010 reports Cannot implicitly convert type 'IEnumerable<RowData>' to 'List<RowData>'. An explicit conversion exists (are you missing a cast?)
OK, where does the CAST go?
Second:
Someone could pass in an invalid colName value (i.e. String.IsNullOrEmpty(colName)) or a null parameter (object value == null).
How would I handle the way my function returns if the input parameters are invalid?
[Solved]
I edited my Select statement (even renamed it per the suggestions here). I had to use a switch to cast to the data type that the data was in, but it does work.
public RowDataCollection SelectRow(string colName, object value) {
if (!String.IsNullOrEmpty(colName) && (value != null) && (0 < Rows.Count)) {
switch (Rows[0][colName].GetValueType()) {
case TableDataType.Boolean:
return new RowDataCollection(Rows.Where(r => (bool)r[colName].Value == (bool)value).ToList());
case TableDataType.Character:
return new RowDataCollection(Rows.Where(r => (char)r[colName].Value == (char)value).ToList());
case TableDataType.DateTime:
return new RowDataCollection(Rows.Where(r => (DateTime)r[colName].Value == (DateTime)value).ToList());
case TableDataType.Decimal:
return new RowDataCollection(Rows.Where(r => (Decimal)r[colName].Value == (Decimal)value).ToList());
case TableDataType.Integer:
return new RowDataCollection(Rows.Where(r => (int)r[colName].Value == (int)value).ToList());
case TableDataType.String:
return new RowDataCollection(Rows.Where(r => r[colName].Value.ToString() == value.ToString()).ToList());
}
}
return null;
}
[Solved (short version)]
Jon Skeet posted this about the same time I posted my solution, and (as always) his code is much nicer.
public RowDataCollection SelectRow(string colName, object value) {
List<RowData> rowList = Rows.Where(r => r[colName].Value.Equals(value)).ToList();
return new RowDataCollection(rowList);
}
#Jon Skeet: If I ever see your face in the same line at some software developer position I'm applying for, I'm just going to turn around and go home.
#Everyone: Thanks for all the help!
The result of a query like that isn't a List<T>, it's an IEnumerable<T>. If you want to convert that into a List<T>, just call ToList:
List<RowData> rowList = (from item in Rows
where item[colName].Value == value
select item).ToList();
As it happens, you're only calling Where in your query. I would rewrite this as:
List<RowData> rowList = Rows.Where(item => item[colName].Value.Equals(value))
.ToList();
I'd also rename the method to something which is obviously filtering rather than projecting, given that the latter is the more common use of the term "select" in LINQ.
As for input parameters - I suggest you validate the arguments and throw an exception if they're not valid:
if (string.IsNullOrEmpty(colName))
{
throw new ArgumentException("colName");
}
You're getting the error message because LINQ Queries return IEnumerable, not List.
If you need a List, it's easy enough:
List<RowData> rowList = (from item in Rows
where item[colName].Value == value
select item).ToList();
You can't directly cast an IEnumerable<RowData> to a List<RowData>, however, there does exist a convenience function Enumerable.ToList<T>(), used like so:
List<RowData> rowList = (from item in Rows
where item[colName].Value == value
select item).ToList();
As for your second question, an exception would occur during the ToList() call as the LINQ expression is evaluated immediately. You have a few options, including throwing ArgumentExceptions or returning an empty list. It depends on your use cases. I'd suggest simply throwing an exception (assuming you have some HasColumn() method on your RowData class):
if (colName == null)
{
throw new ArgumentNullException("colName");
}
else if (!Rows.All(row => row.HasColumn(colName)))
{
throw new ArgumentException("No such column " + colName, "colName");
}
Per your edit, another approach, if a column missing is not necessarily a "problem":
...
// note the change to Any()
else if (!Rows.Any(row => row.HasColumn(colName))
{
throw new ArgumentException("No such column " + colName, "colName");
}
List<RowData> rowList = (from item in Rows
where item.HasColumn(colName)
&& item[colName].Value == value
select item).ToList();
You have to convert IQueriable<> to List<>, by calling ToList();
public RowDataCollection Select(string colName, object value) {
List<RowData> rowList = from item in Rows
where item[colName].Value == value
select item;
return new RowDataCollection(rowList.ToList());
}