I have the following EF query :
var result = (from t in context.Tickets.Include("Priority").Include("Status")
where t.TicketOpenBy.Id == user.Id
select t).Include(t => t.TicketOpenBy);
I also try
context.Tickets.Where(t => t.TicketOpenBy.Id == userId).Include("Priority").Include("Status").Include("TicketOpenBy");
When i receive the list, for each row, the object "TicketOpenBy" has all fields null.
But when i change the "where" with this condition :
"where t.TicketOpenBy.Id != user.Id"
I receive my object with all properties included.
I don't understand this behaviour. What am I doing wrong?
Related
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);
I'm having a hard time trying to display the data from two tables into a view using a linq lambda expression in ASP.net MVC.
I've tried this code:
var idSearchJoin = payoutdb.payout_transaction // your starting point - table in the "from" statement
.Join(payoutdb.payout_remittance, // the source table of the inner join
transaction => transaction.transid, // Select the primary key (the first part of the "on" clause in an sql "join" statement)
remit => remit.transid, // Select the foreign key (the second part of the "on" clause)
(transaction, remit) => new { Transaction = transaction, Remit = remit }) // selection
.Where(transactremit => transactremit.Transaction.senderRefId == searchTxt).ToList();
I've joined the two tables but now my problem is that i can't put it into a view model to be able to display it to a view because the two tables have the same column transid so even if i created a new model to match the values of the result of linq expression it will not match because the transid cannot be initiated twice inside the same view model. Do you have any suggestions on how am i supposed to do this?
I am not sure what you mean by transid cannot be initiated twice. If you want to put your results set to your ViewModel, you need to put it right on your selection or after your query:
Instead of this:
(transaction, remit) => new { Transaction = transaction, Remit = remit }) // selection
Do this (MyViewModel is the name of my View Model):
(transaction, remit) => new MyViewModel()
{ field1 = transaction.transid, field2 = remit.whateverfield, field3 = transaction.whateverfield })
//selection, replace field1 with your correct fields
Then do the filtering (removed the Transaction word) :
.Where(transactremit => transactremit.senderRefId == searchTxt).ToList();
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!
so I have a form with several fields which are criteria for searching in a database.
I want to formulate a query using LINQ like so:
var Coll = (from obj in table where value1 = criteria1 && value2 = criteria2...)
and so on.
My problem is, I don't want to write it using If statements to check if every field has been filled in, nor do I want to make separate methods for the various search cases (criteria 1 and criteria 5 input; criteria 2 and criteria 3 input ... etc.)
So my question is: How can I achieve this without writing an excessive amount of code? If I just write in the query with comparison, will it screw up the return values if the user inputs only SOME values?
Thanks for your help.
Yes, it will screw up.
I would go with the ifs, I don't see what's wrong with them:
var query = table;
if(criteria1 != null)
query = query.Where(x => x.Value1 == criteria1);
if(criteria2 != null)
query = query.Where(x => x.Value2 == criteria2);
If you have a lot of criteria you could use expressions, a dictionary and a loop to cut down on the repetitive code.
In an ASP.NET MVC app, chances are your user input is coming from a form which is being POSTed to your server. In that case, you can make use of strongly-typed views, using a viewmodel with [Required] on the criteria that MUST be provided. Then you wrap your method in if (ModelState.IsValid) { ... } and you've excluded all the cases where the user hasn't given you something they need.
Beyond that, if you can collect your criteria into a list, you can filter it. So, you could do something like this:
filterBy = userValues.Where(v => v != null);
var Coll = (from obj in table where filterBy.Contains(value1) select obj);
You can make this more complex by having a Dictionary (or Lookup for non-unique keys) that contains a user-entered value along with some label (an enum, perhaps) that tells you which field they're filtering by, and then you can group them by that label to separate out the filters for each field, and then filter as above. You could even have a custom SearchFilter object that contains other info, so you can have filters with AND, NOT and OR conditions...
Failing that, you can remember that until you trigger evaluation of an IQueryable, it doesn't hit the database, so you can just do this:
var Coll = (from obj in table where value1 == requiredCriteria select obj);
if(criteria1 != null)
{
query = query.Where(x => x.Value1 == criteria1);
}
//etc...
if(criteria5 != null)
{
query = query.Where(x => x.Value5 == criteria5);
}
return query.ToList();
That first line applies any criteria that MUST be there; if there aren't any mandatory ones then it could just be var Coll = table;.
That will add any criteria that are provided will be applied, any that aren't will be ignored, you catch all the possible combinations, and only one query is made at the end when you .ToList() it.
As I understand of your question you want to centralize multiple if for the sake of readability; if I were right the following would be one of some possible solutions
Func<object, object, bool> CheckValueWithAnd = (x, y) => x == null ? true : x==y;
var query = from obj in table
where CheckValue(obj.value1, criteria1) &&
CheckValue(obj.value2, criteria2) &&
...
select obj;
It ls flexible because in different situations or scenarios you can change the function in the way that fulfill your expectation and you do not need to have multiple if.
If you want to use OR operand in your expression you need to have second function
Func<object, object, bool> CheckValueWithOr = (x, y) => x == null ? false : x==y;
I have a Blogs table related to BlogComments table with a FK.
I need to get, through Linq, all the BlogComments items that match a certain flag
If i do:
db.Blogs.Where(b => b.BlogComments.Where(bc=>bc.Where(bc.Flag1==true));
I get "Cannot implicity convert type IEnumerable to bool"
Which is the best way to solve this problem?
Because this expression:
b.BlogComments.Where(...)
returns an IEnumerable (of BlogComments), but you are then passing it into this method:
db.Blogs.Where(...)
which expects a function that returns a bool, not an IEnumerable.
You probably need something like this:
var blogId = 5;
db.BlogComments.Where(bc => bc.BlogId == blogId && bc.Flag1 == true)
If you need to select comments from multiple blogs, then you could try using Contains:
var blogIds = new [] {1,2,3,4,5};
db.BlogComments.Where(bc => blogIds.Contains(bc.BlogId) && bc.Flag1 == true)
If you want to place criteria on the set of blogs, as well as the comments, then you could do this in one query using a join:
var query = from b in db.Blogs
join c in db.BlogComments on c.Blog equals b
where b.SomeField == "some value"
&& c.Flag1 == true
select c;
You could write it in LINQ form.
var blogs = from b in db.Blogs
join c in db.BlogComments
on b.BlogId equals c.BlogId
where c.Flag1
select b;
If you have a composite key you can write
on new { A = b.BlogKey1, B = b.BlogKey2 }
equals new { A = c.CommentKey1, B = c.CommentKey2 }
If it were me, I would just have another DbSet in your DbContext.
DbSet<BlogComment> BlogComments
and just search through there without going through Blogs.
db.BlogComments.Where(bc => bc.Flag1 == true);
If anyone knows if there's anything wrong in doing so, then I'm all ears :)