Linq to Entities compare DateTime in Sub Query - entity-framework-4

I'm trying to do this subquery:
var query =
from cjto in oContext.t_table_1
join cav in oContext.t_table_2 on cjto.cd_code equals cav.cd_code
where cav.dt_time >=
(from tu in oContext.t_table3
where tu.vl_code == "ABCD"
select tu.dt_check_time)
select cav;
However, I get the error:
Operator '>=' cannot be applied to operands of type 'System.DateTime' and 'System.Linq.IQueryable<System.DateTime?>'
How can I implement such query?
Tks

Ok, I got it... I needed to add the FirstOrDefault() so get the first element
var query =
from cjto in oContext.t_table_1
join cav in oContext.t_table_2 on cjto.cd_code equals cav.cd_code
where cav.dt_time >=
(from tu in oContext.t_table3
where tu.vl_code == "ABCD"
select tu.dt_check_time).FirstOrDefault()
select cav;
Tks

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);

Linq Group and Count in IEnumerable

I have the following LINQ Query in my controller which queries my IEnumerable Collection, the grouping works when I output the results in my view but when I try and add a count on the column I have grouped it fails miserably. I was wondering if anyone could help at all, I have been looking at previous examples but I am missing something obvious.
Grouped //Working fine and returning grouped Descriptions
itemdetails = (from c in db.CLIENTDETAILS
join l in db.LOCATIONS on c.CLIENTNUMBER equals l.CLIENTNUMBER
where c.CLIENTNUMBER == clientNumber
join i in db.ITEMDETAILS on l.LOCNUMBER equals i.LOCNUMBER
where i.LOCNUMBER == l.LOCNUMBER
select i).GroupBy(it => it.DESC).Select(grp => grp.FirstOrDefault()).OrderBy(x => x.DESC)
What I have tried to get Group and Count in LINQ //Not working returning error
itemdetails = (from c in db.CLIENTDETAILS
join l in db.LOCATIONS on c.CLIENTNUMBER equals l.CLIENTNUMBER
where c.CLIENTNUMBER == clientNumber
join i in db.ITEMDETAILS on l.LOCNUMBER equals i.LOCNUMBER
where i.LOCNUMBER == l.LOCNUMBER
select i).GroupBy(it => it.DESC).Select(grp => new {DESC = grp.key, Count = grp.COUNT()}).OrderBy(x => x.DESC)
This give me the following error :-
cannot implicitly convert type system linq iorderedqueryable to system.collections.generic.ienumerable
Thanks for your help as always.
Your two queries are returning different data, the first is returning items of type ItemDetail, while the second query is returning items of an anonymous type.
If you want an IEnumerable of an anonymous type, you will need to declare it using the var keyword, i.e.
var itemdetails = (from c in db.CLIENTDETAILS
join l in db.LOCATIONS on c.CLIENTNUMBER equals l.CLIENTNUMBER
where c.CLIENTNUMBER == clientNumber
join i in db.ITEMDETAILS on l.LOCNUMBER equals i.LOCNUMBER
where i.LOCNUMBER == l.LOCNUMBER
select i).GroupBy(it => it.DESC).Select(grp => new {DESC = grp.key, Count = grp.COUNT()}).OrderBy(x => x.DESC)

Linq left outer join not working using DefaultIfEmpty

Using the technique found on the MSDN article "How to: Perform Left Outer Joins (C# Programming Guide)", I attempted to create a left outer join in my Linq code. The article mentions using the DefaultIfEmpty method in order to create a left outer join from a group join. Basically, it instructs the program to include the results of the left (first) collection even if there are no results in the right collection.
The way this program executes, however, it does so as if the outer join has not been specified.
In our database, AgentProductTraining is a collection of courses our agents have taken. Normally you cannot enter a Course onto it's appropriate table without entering a corresponding value into the CourseMaterials table. However, occasionally this may happen, so we want to make sure we return results even when a Course is listed in AgentProductTraining without any corresponding information in CourseMaterials.
var training = from a in db.AgentProductTraining
join m in db.CourseMaterials on a.CourseCode equals m.CourseCode into apm
where
a.SymNumber == id
from m in apm.DefaultIfEmpty()
where m.EffectiveDate <= a.DateTaken
&& ((m.TerminationDate > a.DateTaken) | (m.TerminationDate == null))
select new
{
a.AgentProdTrainId,
a.CourseCode,
a.Course.CourseDescription,
a.Course.Partner,
a.DateTaken,
a.DateExpired,
a.LastChangeOperator,
a.LastChangeDate,
a.ProductCode,
a.Product.ProductDescription,
m.MaterialId,
m.Description,
a.Method
};
The MSDN example uses a new variable subpet:
var query = from person in people
join pet in pets on person equals pet.Owner into gj
from subpet in gj.DefaultIfEmpty()
select new { person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name) };
So you must use your own "subpet", I rewrote your code using the submat variable:
var training = from a in db.AgentProductTraining
join m in db.CourseMaterials on a.CourseCode equals m.CourseCode into apm
where
a.SymNumber == id
from submat in apm.DefaultIfEmpty()
where
(submat.EffectiveDate <= a.DateTaken || submat.EffectiveDate == null) &&
(submat.TerminationDate > a.DateTaken || submat.TerminationDate == null)
select new
{
a.AgentProdTrainId,
a.CourseCode,
a.Course.CourseDescription,
a.Course.Partner,
a.DateTaken,
a.DateExpired,
a.LastChangeOperator,
a.LastChangeDate,
a.ProductCode,
a.Product.ProductDescription,
MaterialId = (submat==null?-1:submat.MaterialId),
Description = (submat==null?String.Empty:submat.Description),
a.Method
};

Translating SQL statement with dates to Linq-to-Sql for use with EF4

I have the following SQL command:
SELECT CONVERT(varchar, Logged, 103) AS Visited, COUNT(ID) AS Totals
FROM tblStats
GROUP BY CONVERT(varchar, Logged, 103)
ORDER BY Visited DESC
I want to translate this into a L2S statement that can be used with the Entity Framework, but in working with datetime types, I'm getting various errors depending on how I try to attack the problem.
Approach:
var results = from s in db.Stats
group s by (s.Logged.Date.ToString()) into Grp
select new { Day = Grp.Key, Total = Grp.Count() };
Error:
LINQ to Entities does not recognize
the method 'System.String ToString()'
method, and this method cannot be
translated into a store expression.
Approach:
var results = from s in db.Stats
group s by (s.Logged.Date) into Grp
select new { Day = Grp.Key, Total = Grp.Count() };
Error:
The specified type member 'Date' is
not supported in LINQ to Entities.
Only initializers, entity members, and
entity navigation properties are
supported.
What syntax do I need to make the query work?
Try using the EntityFunctions.TruncateTime method:
var results = from s in db.Stats
group s by EntityFunctions.TruncateTime(s.Logged) into Grp
select new { Day = Grp.Key, Total = Grp.Count() };
Do you need the Date section in s.Logged.Date?
Have you tried this:
var results = from s in db.Stats
group s by (s.Logged) into Grp
select new { Day = Grp.Key, Total = Grp.Count() };
I'm assuming that Logged is the property (column in the table).
EDIT: you guys are way to quick.

LINQ Query to Produce Non-Empty Nested Menu?

To see my problem in action, visit www.apoads.com and hover over the "Local Businesses" menu item. It's a series of nested unordered lists generated from a db call. Go ahead and click on a few of the items underneath "Local Businesses", you'll see that most of the categories are empty (the site is very new).
Problem:
I only want to show the categories that actually contain a local business. Here's what my category schema looks like:
int BizCatID - PK,Identity (used in FK relation to the table named Biz)
int? ParentID - BizCatID of this rows parentID, null means no parent
nvarchar Name - name of the category
nvarchar Caption - quick description of the category
What I've tried:
I've tried to update my LINQ query like so:
from c in db.BizCategories where c.ParentID != null && c.Bizs.Count() > 0 select c;
That obviously won't work, cause I'll need the parent category to show if the child category contains a business. So I tried this:
from c in db.BizCategories where c.Bizs.Count() > 0 select c;
This doesn't work either, as parent categories will never have any businesses under them. So it seems like I'll need to do some sort of inverse recursion, but I'm not sure how to do that.
Or, perhaps I'm making things to hard for myself and I need to change my db schemas?
create classes to hold your information like so
public class BusinessCat
{
public string Name{get;set;}
public string Caption{get;set;}
public List<'dunno datatype'> Children{get;set;};
}
var results = from c in BizCategories
where c.ParentID == null
select new BusinessCat{
Name = c.Name,
Caption = c.Caption,
Children = (from d in BizCategories
where d.ParentID == c.BizCatID && d.Bizs.Count() > 0 select d).ToList()
}
and with this you have a list full of Children and you can simply iterate through it with a foreach.
You can also do .Join() extension method for
where d.ParentID == c.BizCatID && d.Bizs.Count()
I'm not sure about the recursion bit but this might get you started. Is a two-level query.
I'm guessing you want to support any number of levels.
var allcats = (from c in db. BizCategories
select c).ToList(); // This will retrieve them all from the database.
var twoLevels = from c in allcats
where c.ParentID == null
select new {
Name = c.Name, Caption = c.Caption,
Children =
from d in allcats
where d.ParentID == c.BizCatID
select d
};
A query like this is getting close to what I need:
from c in BizCategories
where c.ParentID == null
select new {
Name = c.Name, Caption = c.Caption,
Children =
from d in BizCategories
where d.ParentID == c.BizCatID && d.Bizs.Count() > 0
select d
}
I should be able run another LINQ query over these results and pull out exactly what I need. Not at a computer where I can test that now, but will reply once I can. Thanks!

Resources