how can I use FirstOrDefault()? - asp.net-mvc

I have this code and I want to set a value to Viewdate when the expression returns no data:
ViewData["Fix"] = db.PreStatusViws.Where(c => c.LkpNameFix == "1").FirstOrDefault().NumCoefficientFix;
can I set zero or a "Text" for that? I no, what can I do?!
note: FirstOrDefault(null) cause an error.

If I understand your question correctly, the following code should solve your problem:
var p = db.PreStatusViws.Where(c => c.LkpNameFix == "1").FirstOrDefault();
if(p != null)
ViewData["Fix"] = p.NumCoefficientFix;
else
ViewData["Fix"] = 0;

Default will return the default for the data type. If the data type in that place is a reference type (e.g. string) the default value will always be null, and therefore the following .NumsCoefficientFix member will throw a NullReferenceException.
The default value is built into .NET and not changeable, and is always given if the result set contains no value.
#Mikey has already given the code sample in his answer that I would suggest.

If you first select the numeric column, FirstOrDefault will work as you intend, returning either a value or 0 (the default for numeric types):
ViewData["Fix"] = db.PreStatus
.Select (c => c.NumCoefficientFix)
.FirstOrDefault (c => c.LkpNameFox == "1");
If NumCoefficientFix is a nullable type, then use the ?? operator to convert the null into 0:
ViewData["Fix"] = db.PreStatus
.Select (c => c.NumCoefficientFix)
.FirstOrDefault (c => c.LkpNameFox == "1") ?? 0;
Selecting the NumCoefficientFix first is also (slightly) more efficient for LINQ-to-database queries, in that the SQL generated will select only that column.

You just have to select your NumCoefficientFix property before calling FirstOrDefault:
ViewData["Fix"] = db.PreStatusViws
.Where(c => c.LkpNameFix == "1")
.Select(c => c.NumCoefficientFix)
.FirstOrDefault();`
Or in LINQ notation:
ViewData["Fix"] = (from c in db.PreStatusViws
where c.LkpNameFix == "1"
select c.NumCoefficientFix
).FirstOrDefault();

Related

Linq Get Latest Date Query

I am trying to get the latest date based on my controller below but I was hit with this error :
"Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery1[<>f__AnonymousType201[System.Nullable`1[System.DateTime]]]' to type 'System.IConvertible'."
var latestDt = from n in db.Books
where n.id == id
select new { Date = n.dtBookBorrowed};
DateTime dtPlus1Year = Convert.ToDateTime(latestDt);
May I know how do I get just the column latestDate in linq?
You can try this to get list of date order by latest insert to db.
var latestDt = db.Books.Where(n => n.id == id).OrderByDescending(x => x.dtBookBorrowed).Select(x => x.dtBookBorrowed).ToList();
I think if you use
DateTime.Parse(item.dateAsString)
your problem should be solved.
The LINQ query expression you've defined returns a collection of anonymous object with property Date despite there might be only one record match as ID was meant to be unique.
In your case we only need the target field that can be parsed as DateTime and therefore an alternative in fluent syntax would be as following:-
var book = db.Books.SingleOrDefault(book => book.id == id); // gets matching book otherwise null
if (book != null)
{
var borrowedDate = Convert.ToDateTime(book.dtBookBorrowed);
}
Otherwise if you would like to understand more about the behaviour with query syntax which may return multiple results, you may simplify as following which returns collection of DateTime object (i.e. IEnumerable) instead:-
IEnumerable<DateTime> borrowedDates =
from n in db.Books
where n.id == id
select Convert.ToDateTime(n.dtBookBorrowed);

How to use .Contains with Int DataType

The code below is part of the search functionality code that grabs the query string from URL and searches the database.
Everything works great except for one thing which is BatchID. Which throws the below error message. The BatchIDis DataType Int in the database. Due to this reason it's causing an error. I tried casting as (string) however no luck
Error Message
Severity Code Description Project File Line Error CS1061 'int' does
not contain a definition for 'Contains' and no extension method
'Contains' accepting a first argument of type 'int' could be found
(are you missing a using directive or an assembly
reference?) CardDistro E:\wwwroot\CardDistro \CardDistro
\Controllers\CardsController.cs 32
QueriedTransactionList = db.Transactions
.Where(x => x.Card.InCome.InComePayerName.Contains(QueryString) ||
x.Card.InCome.InComePayerEmail.Contains(QueryString) ||
x.Card.InCome.InComePayerTIN.Contains(QueryString) ||
x.BatchID.Contains( (string) QueryString) //Error over here ||
x.Card.Port.PortName.Contains(QueryString)
)
.OrderByDescending(x => x.TTransactionID)
.GroupBy(x => x.BatchID)
.Select(x => x.FirstOrDefault())
.ToList();
If BatchID property is int type , you cannot use Contains as it works on an array. You may check the value directly using == operator.
Since you are using the same string parameter(QueryString) to get the id value as well, you should use the TryParse method to safely parse the string to an int variable value (if it is a valid string representation of an int value) and use that. If your BatchID value is always greater than 0, you can initialize your local variable to 0, and if the querystring has a valid numeric value, parse it and update the local variable and use that in your LINQ expression.
int id = 0;
if (Int32.TryParse(QueryString, out id))
{
}
var results = db.Transactions
.Where(x => x.Card.InCome.InComePayerName.Contains(QueryString) ||
x.Card.InCome.InComePayerEmail.Contains(QueryString) ||
x.Card.InCome.InComePayerTIN.Contains(QueryString) ||
x.Card.Port.PortName.Contains(QueryString) ||
x.BatchID == id
)
.OrderByDescending(x => x.TTransactionID)
.GroupBy(x => x.BatchID)
.Select(x => x.FirstOrDefault())
.ToList();

Unable to catch if a list item name is missing

I have the following code which groupBY my table and select the count based on the model name:-
var IT360Counts = entities.Resources.Where(a => String.IsNullOrEmpty(a.ASSETTAG) && (a.SystemInfo.ISSERVER == true))
.GroupBy(a => a.SystemInfo.MODEL.ToLower())
.Select(g => new
{
Action = g.Key.ToLower(),
ItemCount = g.Count()
}).ToLookup(a => a.Action);
Then i will referecne the var content such as :-
IT360RouterNo = IT360Counts["router"] == null ? 0 : IT360Counts["router"].SingleOrDefault().ItemCount,
The above will work well, unless when the first query does not have any router, then the second statement will always return null exception. so my question is weather there is a way to catch if IT360Counts["router"] exists sor not ?
Thanks
This will happen when IT360Counts["router"] is not null but an empty list. In that case IT360Counts["router"].SingleOrDefault() will return null, so when accessing its ItemCount property you will get a null exception.
This happens because the indexer in the Lookup returns an empty list when the key is not found. See remarks section in msdn. Try checking if the lookup contains the key, IT360Counts.Contains("router"). This way you can do:
IT360RouterNo = IT360Counts.Contains("router") ? IT360Counts["router"].SingleOrDefault().ItemCount : 0,
As a side note, have you also considered using ToDictionary instead of ToLookup? The dictionary key would be your Action and the value the ItemCount, so when retrieving the values you just get the value in the dictionary for a key like "router". If you are you always doing .SingleOrDefault().ItemCount and never expect more than one item with the same Action, you may be better using a dictionary.
For the sake of completion this idea would be:
var IT360Counts = entities.Resources.Where(a => String.IsNullOrEmpty(a.ASSETTAG) &&(a.SystemInfo.ISSERVER == true))
.GroupBy(a => a.SystemInfo.MODEL.ToLower())
.Select(g => new
{
Action = g.Key.ToLower(),
ItemCount = g.Count()
}).ToDictionary(a => a.Action, a => a.ItemCount);
IT360RouterNo = IT360Counts.ContainsKey("router") ? IT360Counts["router"] : 0,
Hope it helps!

LINQ Union Allways returning empty sets

I'm doing some LINQ to look for keywords typed in a textbox. Each keyword ends with ";" and i need to look for itens that contain at least one of those keys.
I thought that i would be able to achieve this with this loop
IEnumerable<ItemFAQ> allResults = null;
foreach (var item in termosPesquisaIsolados)
{
IEnumerable<ItemFAQ> tempResults =
_dbHelpDesk.ItemFAQ
.Where(x => x.DescricaoResposta.Contains(item) || x.TituloTopico.Contains(item))
.ToList()
.Select(x => new ItemFAQ
{
IdPergunta = x.IdPergunta,
TituloTopico = x.TituloTopico,
DescricaoResposta = x.DescricaoResposta.Substring(0, 100)
});
if (allResults != null)
allResults = allResults.Union(tempResults);
else
allResults = tempResults;
}
At first iteration tempResult returns in a test 3 elements then it passes then to allResult, everything ok with that.
The second iteration, tempResult returns 2 ocurrences... then according to code allResult should receive the Union of AllResult and the TempResults, but no matter what i do, when i use the Union clause the result in an Empty Set.
So 3 + 2 = 0 at the end after using Union.
Do you guys can see the mistake at this peace of code or know some issues that could lead to this error ?
Thanks for your time.
try replacing this line:
allResults = allResults.Union(tempResults);
with:
allResults = allResults.Union(tempResults).ToList();

What would LINQ to Entities return when selecting an integer id for a given row name if the record does not exist?

Here's the code:
string name = "myName";
int id = (int)_myDB.ThingTable.Where(thing => thing.ThingName == name)
.Select(thing => thing.ThingId);
I have an error saying System.Linq.IQueryable cannot be converted to int (I'm assuming it's so that I don't end up with a case where no rows are found- no id is returned)
First, how can I cast it to an int?
Second, what gets returned if no record with a ThingName == name exists?
Thanks,
Matt
You need a query expression that returns a scalar. Something like:
myCollection.Where(c => c.X > 0).FirstOrDefault();
In your example it would be:
int id = (int)_myDB.ThingTable.Where(thing => thing.ThingName == name)
.Select(thing => thing.ThingId).FirstOrDefault();
If no row is returned, the default value of the scalar is returned (generally zero in the case of a non-nullable number).
Try using FirstOrDefault() on queries such as that. It will return the default value for the selection if nothing is returned. 0 for numbers, null for objects.

Resources