Convert SQL query to linq in C# with Entity Framework - c#

I need to convert below query to linq in C#. Can someone share a free online tool or if you have good command in linq then please rewrite in C# supportive linq.
select
PaymentHolidayReason as Reason,
EmploymentStatus,
Cast(count(1) as Decimal) as Count,
Cast((select count(1)
from MortgageApplications MortgageApps
where PaymentHolidayReason is not null
and EmploymentStatus is not null) as Decimal) as Total
from
MortgageApplications MortgageApps
where
PaymentHolidayReason is not null
group by
PaymentHolidayReason,
EmploymentStatus

I would suggest you try to use the LinqPad and refer to the link below: http://www.linqpad.net
If not satisfied try: http://www.sqltolinq.com but I prefer LinqPad

i have write below query and it's working as same above sql statement.
var totalCount = _caseManagerContext.MortgageApplications.Where(x => x.PaymentHolidayReason != null && x.EmploymentStatus != null).Count();
var result = from mapp in _caseManagerContext.MortgageApplications
where mapp.EmploymentStatus!=null && mapp.PaymentHolidayReason!=null &&
mapp.LastModifiedDate >= initialDate && mapp.LastModifiedDate <= finalDate
group mapp by new { mapp.PaymentHolidayReason, mapp.EmploymentStatus } into g
select new { g.Key.PaymentHolidayReason, g.Key.EmploymentStatus, MyCount = g.Count(), Total=totalCount };

Related

How can I make this LINQ to SQL where clause with conditions faster?

I have the following LINQ to SQL query but I want to know if there is a faster way to validate data from a post action before adding them in a where clause? ex:
bookFilter = Informations coming from the post action
int count = from b in _libraryContext.Book
join ba in _libraryContext.BookAuthor
on b.Id equals ba.BookId
where (!string.IsNullOrWhiteSpace(bookFilter.Name) ?
b.Name.Contains(bookFilter.Name.ToUpper()) : 1 == 1 )
where (!string.IsNullOrWhiteSpace(bookFilter.Decription) ?
b.Description.Contains(bookFilter.Description.ToUpper()) : 1 == 1)
where (bookFilter.BookId > 0 ? ba.BookId == bookFilter.BookId : 1 == 1)
return count;
I've never used this type of syntax much so I'm sure if you can do it this way, but you can certainly do it with LINQ and build up your query step by step like so:
var query = _libraryContext.Set<Book>();
if(!string.IsNullOrWhiteSpace(bookFilter.Name))
{
query = query.Where(x => x.Name.Contains(bookFilter.Name.ToUpper()));
}
if(!string.IsNullOrWhiteSpace(bookFilter.Description))
{
query = query.Where(x => x.Description.Contains(bookFilter.Description.ToUpper()));
}
if(bookFilter.BookId > 0)
{
query = query.Where(x => x.BookId == bookFilter.Id);
}
return query.Count();
Note: I have omitted the JOIN here as it seems unnecessary, but you can of course do the join in this syntax too if you need it.
You have accepted the solution that #Akinzekeel provided above. However, in the case that you are trying to use a single LINQ query, I would go for the solution below:
bookFilter = Informations coming from the post action
Please note here bookFilter has to be IQueryable!
int count = from b in _libraryContext.Book
join ba in _libraryContext.BookAuthor
on b.Id equals ba.BookId
where (b.Name.Contains(bookFilter.Name.ToUpper()) || string.IsNullOrWhiteSpace(bookFilter.Name)) &&
(b.Description.Contains(bookFilter.Description.ToUpper()) || string.IsNullOrWhiteSpace(bookFilter.Decription)) &&
(ba.BookId == bookFilter.BookId || bookFilter.BookId == 0 )
return count;
If you trace the code above in SQL Profiler, you will see this will generate a single SQL query; something like (OR IS NULL) conditions.
In SQL you could use COALESCE to default ignore parameters -- like the following:
SELECT *
FROM book b
JOIN BookAuthor ba on b.id = ba.Bookid
WHERE COALESCE(UPPER(name), UPPER(b.name)) = UPPER(b.name)
AND COALESCE(UPPER(description), UPPER(b.description)) = UPPER(b.description)
AND COALESCE(bookid, b.book.id) = b.bookid
Recommended pattern is to put something like that in a SP and then call the SP.

Convert SQL query to LINQ or lambda expression in C# and use in EF Core

I have 3 table
Tbl_City , Tbl_GroupCities , Tbl_CtrCar .
I want to convert this SQL query to LINQ or lambda expression in C#
declare #fk_group uniqueidentifier
SELECT #fk_group= FK_Group
FROM dbo.Tbl_User
WHERE UserName='meysam'
SELECT dbo.Tbl_City.ID_City, dbo.Tbl_City.Name_City,COUNT( dbo.Tbl_CtrCar.Cur_year)
FROM dbo.Tbl_City
INNER JOIN dbo.Tbl_CtrCar ON dbo.Tbl_City.ID_City = dbo.Tbl_CtrCar.FK_City
WHERE ID_City IN (SELECT FK_City
FROM dbo.Tbl_GroupCities
WHERE Active=1 AND ID_Group=#fk_group)
GROUP BY ID_City , Name_City
I try it but it's not work
var model = _TblUser.FirstOrDefault(x => x.UserName == "sampleUserName");
var q = _TblGroupCities.Where(x => x.IdGroup == model.FkGroup && x.Active == true);
var sample2 =
(from x in _TblCity
join a in _TblGroupCities on x.IdCity equals a.FkCity
where a.Active == true && a.IdGroup == model.FkGroup
select new
{
x.IdCity,
x.NameCity
}).ToList();
Please take a look here the features you have in your query are not yet implemented. GroupBy and i think also subselects will do an
SELECT * FROM TableName
And in memory it will do the group by or even for each row a new SQL query.
Better to use the RawSql method for this purpose.
But if you realy want to learn LINQ and convert your SQL take a look at LINQPad
This issue is done. I found my problem, I don't Understand use two joins and use group by in Linq
I use this linq for the solution and run
var model = _TblUser.SingleOrDefault(x => x.UserName == type.UserName);
var q = _TblGroupCities.Where(x => x.IdGroup == model.FkGroup && x.Active == true);
tblCityViewModel = new List<MohasebKhodro.ViewModels.TblCityViewModel>();
var sample2 =
(from x in _TblCity
join a in _TblGroupCities on x.IdCity equals a.FkCity
where a.Active == true && a.IdGroup == model.FkGroup
select new
{
x.IdCity,
x.NameCity
}).ToList();
foreach (var item in sample2)
{
var er = _TblCtrCar.Where(x => x.FkCity == item.IdCity).Max(x => x.CurYear);
tblCityViewModel.Add(new MohasebKhodro.ViewModels.TblCityViewModel
{
IdCity = item.IdCity,
NameCity = item.NameCity,
MaxCurrentYear = Convert.ToString(er)
});
}

Can't compare dates using SQLite with EF6

I'm trying to compare dates using Linq to Entities on a SQLite database. The following code works, but I need to trim off the time portion to get the correct results.
return (from c in Context.Car
join d in Context.Driver on c.CarID equals d.DriverID
join r in Context.Rides on c.CarID equals r.RideID into rideJoin
from rides in rideJoin.DefaultIfEmpty()
where c.IsActive && d.IsActive
group rides by new { c.CarID, d.FullName, d.HireDate, d.FirstPayRiseDate } into grp
select new MyCustomClass
{
CarID = grp.Key.CarID,
Driver = grp.Key.FullName,
NumberOfRides = grp.Count(x => x != null && x.RideDate >= grp.Key.HireDate && x.RideDate <= grp.Key.FirstPayRiseDate)
}).OrderBy(x => x.Driver ).ToList();
I've tried using System.Data.Entity.DBFunctions like so and I get this error:
NumberOfRides = grp.Count(x => x != null && DbFunctions.TruncateTime(x.RideDate) >= grp.Key.HireDate && DbFunctions.TruncateTime(x.RideDate) <= grp.Key.FirstPayRiseDate)
SQL logic error or missing database no such function: TruncateTime
I also get the same error with DBFunctions.DiffDays()
I've also tried casting to Date like so and get this error:
NumberOfRides = grp.Count(x => x != null && x.RideDate.Date >= grp.Key.HireDate && x.RideDate.Date <= grp.Key.FirstPayRiseDate)
'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported
What gives? How am I supposed to do Date functions in Linq to Entities with SQLite??
I need to trim off the time portion to get the correct results
No you don't. If you want to include the rows from startDate through endDate inclusive then just use
... && x.RideDate >= startDate && x.RideDate < endDate.AddDays(1)
(Note that the second comparison is now "strictly less than".)
How are you storing dates on the database ? as unix time integrs ?
in that acse you can amend your connection string to include this following config setting and it will make it easy to read the datetime value via EF.
datetimeformat=UnixEpoch;datetimekind=Utc
So something like :
data source="|DataDirectory|\data.sqlite";datetimeformat=UnixEpoch;datetimekind=Utc
Ref: https://stackoverflow.com/a/24323591/3660930

LINQ Syntax for Current Revision

How can I write this SQL statement using C# and LINQ? I am quering an Oracle database and the table has multiple revisions of the records. Therefore, I want onyl the current revision of each record contained in the table.
The SQL looks like this:
select TP_ID, TP_TEXT, TP_DEFN_SAKEY
from TP_DEFN tp1
where tp1.TP_ACTIVE_FLAG = 'Y' and
tp1.FAMILY_ID = 1 and
tp1.TP_DEFN_REV_DTS = (select max(TP_DEFN_REV_DTS)
from TP_DEFN tp2
where tp2.family_id = tp1.family_id and tp2.tp_id = tp1.tp_id )
order by TP_ID
TP_DEFN_REV_DTS is the date time field that stores the current revision.
I am a beginner with LINQ and have been struggling to find an workable solution. Every time that I try grouping in the LINQ query I get an error
GroupBy is not supported
Try something like this:
var res =
from tp1 in TP_DEFN
where tp1.TP_ACTIVE_FLAG == "Y" &&
tp1.FAMILY_ID == 1 &&
tp1.TP_DEFN_REV_DTS == (from tp2 in TP_DEFN
where tp2.FAMILY_ID == tp1.FAMILY_ID &&
tp2.TP_ID == tp1.TP_ID
select tp2.TP_DEFN_REV_DTS).Max()
orderby tp1.TP_ID
select new
{
tp1.TP_ID,
tp1.TP_TEXT,
tp1.TP_DEFN_SAKEY
};
Off the top of my head, and not knowing which LINQ provider you're using...
var q = from tp1 in Context.TP_DEFN
where tp1.TP_ACTIVE_FLAG == "Y"
&& tp1.FAMILY_ID == 1
&& tp1.TP_DEFN_REV_DTS
== Context.TP_DEFN.Where(tp2 => tp2.FAMILY_ID == tp1.FAMILY_ID
&& tp2.TP_ID == tp1.TP_ID)
.Max(tp2 => tp2.TP_DEFN_REV_DTS)
orderby tp1.TP_ID
select new
{
tp1.TP_ID,
tp1.TP_TEXT,
tp1.TP_DEFN_SAKEY
};
If you're using entity framework or linq-to-sql, you can just pass the direct sql if you want (although that'll prevent change tracking, at least by default).
For EF, use ObjectContext.ExecuteStoreQuery: http://msdn.microsoft.com/en-us/library/dd487208.aspx
For L2S, use DataContext.ExecuteQuery: http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.executequery.aspx

How do I format date literals in dynamic linq?

I am using dynamic Linq to return data for user-input search criteria. My query is working fine except for the user selected dates. My current code is:
StringBuilder whereClause = new StringBuilder();
if (startDate.HasValue || endDate.HasValue)
{
DateTime searchStartDate = startDate.HasValue ? startDate.Value : DateTime.MinValue;
DateTime searchEndDate = endDate.HasValue ? endDate.Value : DateTime.MaxValue;
whereClause.AppendFormat("Date >= {0} && Date <= {1}",
searchStartDate.Date.ToUniversalTime(),
searchEndDate.Date.ToUniversalTime());
}
if (whereClause.Length > 0)
{
return (from p in this.repository.GetQueryable<Party>() select p)
.Where(whereClause.ToString())
.ToList();
}
The query falls over because the comparison is being done between a DateTime field and a Int32 field, meaning the query has interpreted my date literals as integers.
How should I be formatting the dates?
Use
.Where("Date >= #0 && Date <= #1",
searchStartDate.Date.ToUniversalTime(),
searchEndDate.Date.ToUniversalTime())
instead.
In reply to Val's comment:
OK, then you can do:
whereClause.AppendFormat("Date.ToString() >= \"{0}\" && Date.ToString() <= \"{1}\"",
searchStartDate.Date.ToUniversalTime(),
searchEndDate.Date.ToUniversalTime());
You have to convert the Date in the query to a string and then compare it a quoted string literal. Without the quotes the parser is inerpreting the numbers inserted into the where clause as integers - what should explain the error you originally got.
Why are you parsing strings in a LINQ expression? The entire point of LINQ is to avoid that.
var q = from p in this.repository.GetQueryable<Party>() select p;
if (startDate.HasValue || endDate.HasValue)
{
var searchStartDate = startDate.HasValue ? startDate.Value : DateTime.MinValue;
var searchEndDate = endDate.HasValue ? endDate.Value : DateTime.MaxValue;
return
q.Where (p=> p.Date >= searchStartDate.ToUniversalTime()
&& p.Date <= searchEndDate.ToUniversalTime()).ToList();
}
return q.ToList();
UPDATE:
In response to comments: I'm building that one at run-time. The question isn't run-time vs compile-time; it's "in strings" vs "in code". StringBuilder lets you append text; LINQ lets to chain lamdbas. It all works out the same --- except your code is type-safe and syntax checked using lambdas.
To demostrate this concept further, the following code compiles & runs fine, and allows to you to change the Where clause based on the values of oddsOnly and lowerLimit.
int[] nums = {1,2,3,4,5,6,7,8,9,10};
bool oddsOnly = true;
bool lowerLimit = 5;
var q = from i in nums select i;
if (oddsOnly)
q = q.Where( n=> n%2 == 1);
if (lowerLimit != 0)
q = q.Where( n=> n >= lowerLimit);
foreach(var i in q)
Console.WriteLine(i);
Depending on how you set those values, it will use zero, one or both of the where clauses.
The Dynamic LINQ string would need to look something like:
"Date >= DateTime(2015, 10, 21)"
This is mentioned in the documentation in the DynamicQuery project in the download mentioned at http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library.
Note, there isn't a new before the DateTime constructor.
I tried this and it works. I'm using Telerik's RadGrid control for ASP.NET AJAX. The grid builds the filter string and I needed to add the filter to my query to get the filter to execute in the database using LINQ to Entities. The problem is that the generated filter needed to be altered a little for it to work with LINQ to Entities as opposed to LINQ to Objects. It was doing a DateTime.Parse() which isn't supported in LINQ to Entities.

Categories