I've got this stored procedure I'd like to convert to LINQ to SQL, but I'm having a bit of trouble because I'm new to LINQ (and actually, I'm no SQL guru) and I am not getting the expected results. (I tried calling the SPROC from LINQ to SQL but when I send in the Period datetime as parameter on the SPROC I get some error on L2S about the parameter being nullable but I sent it also non-nullable and I still get the same error.) Below is the SQL:
SELECT Persons.IDPerson,Persons.Name,Persons.PaternalName,Departments.DepartmentName,Jobs.Title, Persons.HireDate, Terminations.TerminationDate, Terminations.HireDate
FROM Persons left outer join Terminations on Persons.IDPerson = Terminations.IDPerson
left outer join Departments on Departments.idDepartment = Persons.IdDepartment
left outer join Jobs on Jobs.IDJob = Persons.IDJob
WHERE (Terminations.IDTermination is null OR Terminations.TerminationDate >= #Period)
and Terminations.HireDate <= #Period OR Persons.HireDate <=#Period
ORDER BY Persons.HireDate, Terminations.HireDate asc
This is my LINQ code so far (it does compile but it doesn't give me the records I expect) The Criteria.Period is a nullable datetime:
result = from emp in HRSystemDB.Persons.OfType<Employee>()
join term in HRSystemDB.Terminations on emp.IDPerson equals term.IDPerson into all
from aHire in all.Where(t => (t.IDTermination == null || t.TerminationDate.Date >= Criteria.Period.Value.Date)
&& t.HireDate.Value.Date <= Criteria.Period.Value.Date
|| emp.HireDate.Date <= Criteria.Period.Value.Date).DefaultIfEmpty()
select new DepartmentHeadCountQuery
{
FullName = emp.Name + " " + emp.PaternalName,
Department = emp.Department.DepartmentName,
JobTitle = emp.Job.Title,
TermDate = aHire.TerminationDate,
EHiredDate = emp.HireDate,
TermHireDate = aHire.TerminationDate
};
Thanks in advance.
This (free only for trial) can be usefull: http://www.sqltolinq.com/
Linqer is a SQL to LINQ converter tool.
It will help you to learn LINQ and convert your existing SQL statements.
Not every SQL statement can be converted to LINQ, but Linqer covers many different types of SQL expressions.
Linqer supports both .NET languages C# and Visual Basic.
And a totally free tool:
http://www.linqpad.net/
LINQPad is also a great way to learn LINQ: it comes preloaded with 200 examples from the book, C# 3.0 in a Nutshell. There's no better way to experience the coolness of LINQ and functional programming.
I know this question it's old, but I think it's need a correct answer, I get to this questing searching for a LINQ equivalent of the IN SQL Keyword and see that the equivalent LINQ code for this query are not provided, maybe the Original author answer this question some time ago, but I leave this for other people searching in the internet:
I got to answers one if you like to have Left Outer Joins:
var query = from emp in context.Persons
join ter in context.Terminations on emp.Id equals ter.IdPerson into terminations
join dep in context.Departments on emp.IdDeparment equals dep.IdDepartment into departments
join job in context.Jobs on emp.IdJob equals job.IdJob into jobs
from ter in terminations.DefaultIfEmpty() //Does an Left Outer Join
from dep in departments.DefaultIfEmpty()
from job in jobs.DefaultIfEmpty()
where (ter.IdTermination == null || ter.TerminationDate >= period)
&& (ter.HireDate <= period || emp.HireDate <=period)
select new
{
emp.Id,
emp.Name,
emp.PaternalName,
dep.DepartmentName,
job.Title,
emp.HireDate,
ter.TerminationDate,
TerminationHireDate=ter.HireDate
};
one using Inner Joins
var query = from emp in context.Persons
join ter in context.Terminations on emp.Id equals ter.IdPerson
join dep in context.Departments on emp.IdDeparment equals dep.IdDepartment
join job in context.Jobs on emp.IdJob equals job.IdJob
where (ter.IdTermination == null || ter.TerminationDate >= period)
&& (ter.HireDate <= period || emp.HireDate <=period)
select new
{
emp.Id,
emp.Name,
emp.PaternalName,
dep.DepartmentName,
job.Title,
emp.HireDate,
ter.TerminationDate,
TerminationHireDate=ter.HireDate
};
the variable context is the Linq to SQL or Linq to Entity Context
Related
I am converting some SQL queries to Linq (Entity Framework). Most of queries are working fine, but I am facing little problem with the following one.
When I try this query in SQL Server Management Studio, it returns multiple records.
SELECT
bDrillDown,
Icon
FROM
dbo.Checklist
INNER JOIN
dbo.Codes ON Checklist.iCodeID = Codes.iCodeID
AND Codes.bDeleted = 0 AND Codes.bObsolete = 0
INNER JOIN
dbo.CodeGroup ON Codes.iGroupID = CodeGroup.iGroupID
AND CodeGroup.bDeleted = 0 AND CodeGroup.bInspection = 1
INNER JOIN
dbo.CodeInspectionTypeV ON Cast(LEFT(Checklist.LongKey, 6) as int) = CodeInspectionTypeV.InspectionTypeID
WHERE
Checklist.bDeleted = 0
ORDER BY
iChecklistID
When I convert it into LINQ query like:
var checkList = from checklist in db.Checklists
join code in db.Codes on checklist.iCodeID equals code.iCodeID
where code.bDeleted == false && code.bObsolete == false
join codeGroup in db.CodeGroups on code.iGroupID equals codeGroup.iGroupID
where codeGroup.bDeleted == false && codeGroup.bInspection == true
join codeInspectionType in db.CodeInspectionTypeVs on checklist.LongKey.Substring(0, 6) equals codeInspectionType.InspectionTypeID.ToString()
where checklist.bDeleted == false
orderby checklist.iChecklistID
select new
{
checklist.iChecklistID,
InspectionTypeID = checklist.LongKey.Substring(0, 6).ToString()
};
It does not return any records, only an empty array.
The problem is apparently in the following join condition
on checklist.LongKey.Substring(0, 6) equals
codeInspectionType.InspectionTypeID.ToString()
which is not equivalent to the SQL query one.
Unfortunately EF does not support string to numeric data conversions, so your attempt is good, but doesn't work when the string value contains leading zeroes as in your case.
To make it work, you need to left pad with zeroes the result of the codeInspectionType.InspectionTypeID.ToString(), which can be done (at least in the latest EF6.1.3) by using the DbFunctions.Right canonical function (similar to how to sort varchar column containing numeric values with linq lambdas to Entity):
on checklist.LongKey.Substring(0, 6) equals
DbFunctions.Right("00000" + codeInspectionType.InspectionTypeID, 6)
Try to add "into [an alias name]" at the end of join line.
After that add a from line using that alias name
after that use that alias name in the where line
from checklist in db.Checklists
join code in db.Codes on checklist.iCodeID equals code.iCodeID into Temp1
from t1 in Temp1
where t1.bDeleted == false && t1.bObsolete == false
This is my Query in SQL :
Select distinct * from tr.Table1
Left Outer join tr.Table2 on tr.Table1.ID = tr.Table2.ID
Left Outer join tr.Table3 on tr.Table2.AId= tr.Table3.ID
where tr.Table1.Deleted =1 and tr.Table1.Ready=1 and tr.Table1.Show=0
The query is working in SQL and gives the expected results.The thing here is that I want the equivalent of this using LINQ. I have tried some variations in LINQ queries such as :
var query = from p in _ctx.Table1
join s in _ctx.Table2 on p.Id equals s.Id into bag1
from to in bag1.DefaultIfEmpty()
join tx in _ctx.Table3 on to.AId equals tx.Id into bag2
from ts in bag2.DefaultIfEmpty()
select new
{
ContactNo = to.Table1.ContactNo
};
But it always doesn't return all the field values. Some are returned as NULL. Also tried referring to some other link as well but they all focus on joining with the parent table whereas I have to join one of the joined tables with the other one. So here I am, struggling with this.
This is the output that I'm getting as of now. Some values are null. The field has values but due to some joining issue, they are returned as NULL.
Guidance here is appreciated. Thank you.
Your query looks fine to me, the reason why you must be getting the Nulls is because when we use DefaultIfEmpty, it returns null for non-matching rows, thus you need to handle that while fetching the actual results. Try doing something like this:-
var query = from p in _ctx.Table1
join s in _ctx.Table2 on p.Id equals s.Id into bag1
from to in bag1.DefaultIfEmpty()
join tx in _ctx.Table3 on to.AId equals tx.Id into bag2
from ts in bag2.DefaultIfEmpty()
select new
{
ContactNo = to == null ? String.Empty : to.Table1.ContactNo
};
Assuming, ContactNo to be of type String, I have used String.Empty you can use any default value.
Really odd issue that I cant work out.
I am trying to join two tables in a linq statement to only retrieve records where the record in table 1 has no related rows in table 2.
I have used Joins before but for some reason I cant get VS to recognise the second table in the linq statement.
EG.
var result =
(from pc in _dataSource.Payments
join bc in _dataSource.BouncedCheques
on pc.PaymentID != bc.PaymentID //This is where the error occurs, VS does not recognise "bc"
where pc.CustomerNumber == getAccountNumber
& pc.IsDeleted == false
orderby pc.PaymentDate descending
select new PaymentAllocation
{
PaymentId = pc.PaymentID,
PaymentDate = pc.PaymentDate,
CustomerNumber = pc.CustomerNumber,
ChequeReference = pc.ChequeReference,
PaymentValue = pc.PaymentValue,
AllocatedValue = pc.AllocatedValue,
UnallocatedValue = pc.PaymentValue - pc.AllocatedValue,
ReceivedBy = pc.ReceivedBy,
PaymentType = pc.PaymentType,
PostedDate = pc.PostedDate
});
Basically the problem is that the variable "bc" does not seem to be recognised, however I have several other similar Linq queries that all work well
Any ideas?
Your problem is that the syntax for join uses the keyword equals and not standard boolean operators.
Try replacing your join by a cartesian product of your tables:
from pc in _dataSource.Payments
from bc in _dataSource.BouncedCheques
where
pc.PaymentID != bc.PaymentID
&& pc.CustomerNumber == getAccountNumber
& pc.IsDeleted == false
In the join clause you should use the equals keyword:
try:
on pc.PaymentID equals bc.PaymentID
Hi im kinda new to linq to sql I know about the basics. The problem is I want to do a left join in a query. There are 3 tables in the query.
Claimants ( all rows should be returned from this table)
Claim
User
The query should return all Users who have Claimants. This is done through the many to many table Claim. But regardless of Users all Claimants should be returned. Thus the left join on Claimants.
I have the following query
var d = (from Claimants in DB.Claimants
join Claims in DB.Claims on Claimants.Claiment_ID equals Claims.Claiment_ID
join Users in DB.Users on Claims.User_ID equals Users.User_ID
where (Claimants.TrialDate.Value >= dtDayStart & Claimants.TrialDate <= dtDayEnd)
select new
{
ClaimantFirstName = Claimants.FirstName,
ClaimantLasname = Claimants.LastName,
ClaimantsID = Claimants.IDNumber,
Claimants.OurReference,
Claimants.TrialDate,
InterviewStart = Claims.DateTimeStart,
InterviewEnd = Claims.DateTimeEnd,
Claims.Priority,
UserFirstname = Users.FirstName,
UserLastName = Users.LastName,
UserID = Users.IDNumber
});
I have tried using an into statement as follows but with no luck
var d = (from Claimants in DB.Claimants
join Claims in DB.Claims on Claimants.Claiment_ID equals Claims.Claiment_ID
into TheClaimants
from Claims in TheClaimants.DefaultIfEmpty()
join Users in DB.Users on Claims.User_ID equals Users.User_ID
where (Claimants.TrialDate.Value >= dtDayStart & Claimants.TrialDate <= dtDayEnd)
select new
{
ClaimantFirstName = Claimants.FirstName,
ClaimantLasname = Claimants.LastName,
ClaimantsID = Claimants.IDNumber,
Claimants.OurReference,
Claimants.TrialDate,
InterviewStart = Claims.DateTimeStart,
InterviewEnd = Claims.DateTimeEnd,
Claims.Priority,
UserFirstname = Users.FirstName,
UserLastName = Users.LastName,
UserID = Users.IDNumber
});
I would appreciate it if someone could point me in the right direction as to how to use these joins left right correctly and explain how the work. Thank you very much in advance.
var d = (from Claimants in DB.Claimants
join Claims in DB.Claims on Claimants.Claiment_ID equals Claims.Claiment_ID)
.DefaultIfEmpty()
join Users in DB.Users on Claims.User_ID equals Users.User_ID
where (Claimants.TrialDate.Value >= dtDayStart & Claimants.TrialDate <= dtDayEnd)
.DefaultIfEmpty()
select new
{
ClaimantFirstName = Claimants.FirstName,
ClaimantLasname = Claimants.LastName,
ClaimantsID = Claimants.IDNumber,
Claimants.OurReference,
Claimants.TrialDate,
InterviewStart = Claims.DateTimeStart,
InterviewEnd = Claims.DateTimeEnd,
Claims.Priority,
UserFirstname = Users.FirstName,
UserLastName = Users.LastName,
UserID = Users.IDNumber
});
Left outter join
You must know a Luan. If you want all the Claiments to return start by selecting from Claiments and then left join onto the other tables.
Try the following :
LINQ to SQL Left Outer Join
In LINQ, the ".Join()" extension method is the equivalent of SQL inner join.
For outer joins you have to use the ".GroupJoin()" extension method.
Assuming you know the .Join well, the GroupJoin is simple to use. I have to admit that when I first needed to do an outer join in LINQ it was damn hard to find out. I cannot fanthom why did they call it like that.
Although in VB.Net, here's an article that presents various SQL constructs translated into LINQ syntax, even if in VB, still easy to convert to extension methods: http://blogs.msdn.com/b/vbteam/archive/2007/12/31/converting-sql-to-linq-part-6-joins-bill-horst.aspx?Redirected=true
EDIT: #DavidB posted in his comments a much better solution, but only if you can use some ORM navigational properties. If you don't have them, then GroupJoin is probably the most reasonable
Actually I think I might have fixed it, gonna do some testing, I wll post my solution if it works.
I am migrating an older DB system over to LINQ, I'm having trouble converting a few of the SQL statements though:
SELECT * FROM cities
INNER JOIN deals ON cities.cityId = deals.CityID
INNER JOIN countries ON cities.countryID = countries.CountryId
WHERE deals.endDate >= (someDate)
AND countries.CountryId = (1)
AND deals.soldout = (false)
I've done some research, but I can't get it to work. Here is the LINQ statement I came up with:
var deals = from d in db.deals
join city in db.cities on d.CityID equals city.cityId
join country in db.countries on city.countryID equals country.CountryId
where d.endDate > DateTime.Today && country.CountryId == 1 && d.soldOut == false
select d;
Is there some particular way to use 2 joins in LINQ?
Sorry, I had a formatting error: the statement is meant to select all the deals that have a city who's countryID = 1
You do not need the 2nd join if you have a country code for the city...
var deals = from d in db.deals
join city in db.cities on d.CityID equals city.cityId
where d.endDate > DateTime.Today &&
city.CountryId == 1 && d.soldOut == false
select d;
If you want columns from all tables involved, you can use an anonymous type for that.
select new {d, city, country}