I have the following SQL statement
SELECT
c.CorpSystemID, c.SystemName ,
case when a.TaskItemID is NULL then 'false' else 'true' end as Assigned
FROM CorpSystems c
LEFT OUTER JOIN
(SELECT CorpSystemID, TASKItemID
FROM AffectedSystems
where TASKItemID = 1) a ON c.CorpSystemID = a.CorpSystemID
Can anyone please help me to convert this statement to LINQ?
Thank you.
Ok so assume you've got a list of your CorpSystem objects in a variable called Corpsystems and a list of your AffectedSystem objects in a variable called AffectedSystems. Try the following:
Edit: For a join on all Affected Systems, try this:
var matches = from c in CorpSystems
join a in AffectedSystems on c.CorpSystemId equals a.CorpSystemId into ac
from subSystem in ac.DefaultIfEmpty()
select new
{
c.CorpSystemId,
c.SystemName,
Assigned = subSystem != null && subSystem.TaskItemId != null
};
Or for just AffectedSystems that have a TaskItemId of 1:
var matches = from c in CorpSystems
join a in AffectedSystems.Where(as => as.TaskItemId == 1)
on c.CorpSystemId equals a.CorpSystemId into ac
from subSystem in ac.DefaultIfEmpty()
select new
{
c.CorpSystemId,
c.SystemName,
Assigned = subSystem != null && subSystem.TaskItemId != null
};
See the answers to the following SO question SQL to LINQ Tool, assuming that you do not want to go through the process by hand.
Related
I've got two tables that I'm trying to join together with an ID, but only select rows from Table A, where a value in Table B is null.
I tried this:
var dbXMLSoccerTeams = (from dbXMLSoccerTeam in data.EFXMLSoccerTeam
where dbXMLSoccerTeam.ID == (from dbMatchTeam in data.EFMatchingTeamIDs
where dbMatchTeam.SmarketsID == null
select dbMatchTeam.XMLSoccerID)
select dbXMLSoccerTeam);
But I get an error saying that operator == can not be used to compare int to iQueryable int
It seems to me that you should actually use a join:
var dbXMLSoccerTeams = from dbXMLSoccerTeam in data.EFXMLSoccerTeam
join dbMatchTeam in data.EFMatchingTeamIDs
on dbXMLSoccerTeam.ID equals dbMatchTeam.XMLSoccerID
where dbMatchTeam.SmarketsID == null
select dbXMLSoccerTeam;
Try:
var dbXMLSoccerTeams = (from dbXMLSoccerTeam in data.EFXMLSoccerTeam
from dbMatchTeam in data.EFMatchingTeamIDs
where dbMatchTeam.SmarketsID == null
&& dbXMLSoccerTeam.ID == dbMatchTeam.XMLSoccerID
select dbXMLSoccerTeam)
I'm using Telerik Open Access. I have two separate projects that have Open Access data and then a third project that has the bulk of my code. I've been working on a way to convert a simple (at least I thought it was) SQL query to LINQ so that I can get the data I need. I have not been successful. I've had to break a single LINQ query into separate queries, because of the need for the Trim() function (I think). This has led to a lengthy piece of code and I'm still not getting the same results as my SQL query.
So my question is, is there anyway to use SQL instead of LINQ to access the data in the Open Access projects? If so, can you show me the syntax to do that for my query?
If it is not possible to use SQL, can you show me show me the proper way to convert my SQL query into LINQ so that I get the same results?
Thank you.
My SQL query is
SELECT DISTINCT us2.ccustno, us2.dispname, us2.csiteno, so.s1_name
FROM [DALubeDeacom].[dbo].[dmbill] bi
INNER JOIN [DALubeDeacom].[dbo].[dmso1] so
ON bi.bi_s1id = so.s1_id
INNER JOIN [DALubeNew].[dbo].[usersecurity] us2
ON so.s1_name = us2.cparentno
WHERE
us2.ctype = 'JOBSITE'
AND us2.csiteno is not null
AND us2.csiteno != ''
AND bi.bi_smid = '22'
ORDER BY us2.csiteno
My LINQ query is
public List<DataModelSample> GetLocationsBySalesNo(string salesNo)
{
int iSalesNo = int.Parse(salesNo.Trim());
try
{
var dmso = (
from so in deacom.Dmso1
join qt in deacom.Dmbills
on so.S1_id equals qt.Bi_s1id
where qt.Bi_smid == iSalesNo
select new Dmso1
{
S1_id = so.S1_id
, S1_name = so.S1_name.Trim()
}
);
var usec = (
from us in dbContext.Usersecurities
where us.Cparentno != null && us.Cparentno.Trim() != "" && us.Ctype.Trim() == "JOBSITE" && us.Csiteno.Trim() != ""
select new Usersecurity
{
Ccustno = us.Ccustno.Trim(),
Csiteno = us.Csiteno.Trim(),
Dispname = us.Dispname.Trim(),
Cparentno = us.Cparentno.Trim()
}
);
var customers =
(
from us in usec
join so in dmso
on us.Cparentno equals so.S1_name
select us
);
customers = customers.GroupBy(x => x.Csiteno).Select(x => x.First());
List<DataModelSample> listLocations =
(
from c in customers
select new DataModelSample
{
customerID = c.Ccustno
,
origLocationName = c.Csiteno + " " + c.Dispname
,
origLocationID = c.Csiteno
}
).OrderBy(x => x.origLocationID).ToList();
return listLocations.ToList();
}
catch (Exception ex)
{
throw ex;
}
} // GetLocationsBySalesNo(userInfo.csalesno)
Edit 1 - 2-19-16
Tried a suggestion by ViktorZ. His query was similar to the one I first tried. It returned the error "Identifier 'Ctype' is not a parameter or variable or field of 'DALube_DeacomModel.Dmbill'. If 'Ctype' is a property please add the FieldAlias or Storage attribute to it or declare it as a field's alias." From an online search, it looked like this was do to "extended fields". I don't seemed to be using such fields. The only way I could get around this error was to break it into the smaller LINQ queries in my original question, which didn't produce the right results. Any suggestions?
Here's the code:
var query = (from bill in deacom.Dmbills
join so in deacom.Dmso1 on bill.Bi_s1id equals so.S1_id
join us in dbContext.Usersecurities on so.S1_name equals us.Cparentno
where us.Ctype == "JOBSITE"
&& us.Csiteno != null
&& us.Csiteno != string.Empty
&& bill.Bi_smid == iSalesNo
select new
{
ccustno = us.Ccustno.Trim(),
dispname = us.Dispname.Trim(),
csiteno = us.Csiteno.Trim(),
s1_name = so.S1_name.Trim()
}).Distinct();
One very crude approximation of your SQL query is:
var query = (from bill in deacom.Bills
join so in deacom.LubeDeacom on bill.bi_s1id equals so.s1_id
join us in deacom.UserSecurity on so.s1_name equals us.cparentno
where us.ctype = "JOBSITE"
&& us.csiteno != null
&& us.csiteno != string.Empty
&& bill.smid = '22'
order by us.csiteno
select new
{
us.ccustno.Trim(),
us.dispname.Trim(),
us.csiteno.Trim(),
so.s1_name.Trim()
}).Distinct();
// to check the translation result
string sql = query.ToString()
// to get the results
var result = query.ToList()
If this is not working for you, you can always fall back to Telerik Data Access ADO.NET API. Here is a documentation article how to use it.
I need help converting some an SQL select into LINQ
Here is the original SQL:
Select Top 1 IsNull(ct.Template, t.Template) as Template
From Template t
Left Outer Join ClientTemplate ct On t.TemplateTypeId = ct.TemplateTypeId And ct.ClientId = 149
Where t.TemplateTypeId = (Select TemplateTypeId From QuoteType Where QuoteTypeId = 7)
Order By t.Version DESC, ct.Version DESC
I'm using Entity Framework and have entities for QuoteTypes, ClientTemplates and Templates.
The above SQL gets the Template from the ClientTemplate table for client 149 (uses a variable in the real code) for a particular QuoteType. If there is no entry in the CLientTemplate table then it returns the Template from the main Template table for the same QuoteType!
My idea was to query the QuoteType first and then query the ClientTemplate table to see if one exists and if not query the Template table instead. The problem is this will result in three queries but I'm sure it can be done in one swoop!?
Can anyone have a go at writing the LINQ for me?
Here's my mess so far:
QuoteType quoteType = (from qt in this.entities.QuoteTypes where qt.QuoteTypeID == this.SelectedNewQuoteTypeID select qt).First();
if (quoteType != null && quoteType.TemplateTypeID.HasValue)
{
int quoteTypeTemplateTypeID = (int)quoteType.TemplateTypeID;
var query = (from t in this.entities.Templates
join ct in this.entities.ClientTemplates on t.TemplateTypeID equals ct.TemplateTypeID
into a
from b in a.DefaultIfEmpty(new ClientTemplate())
where t.TemplateTypeID == quoteTypeTemplateTypeID
orderby t.Version descending
select new
{
T1 = t.Template1,
T2 = b.Template
}).First();
// Check the query to see if T1 and T2 are null and use whichever one isn't!
// TODO !!!
}
else
{
return string.Empty;
}
I kind of gave up once I got that far and posted this! My example still does two queries and does not select based on the client ID. It also does not have the second order by on the client template table.
I've inherited the original SQL statement so maybe the problem is with that being badly written in the first place!?
Over to you...
I haven't tested it but maybe you could try something like this
from t in this.entities.Template
from ct in this.entities.ClientTemplate.Where(x => t.TemplateTypeId == ct.TemplateTypeId && ct.ClientId == 149).DefaultIfEmpty()
where t.TemplateTypeId == (from x in this.entities.QuoteType where x.QuoteTypeId == 7 select x.TemplateTypeId).FirstOrDefault()
orderby t.Version descending, ct.Version descending
select new { ct.Template == null ? t.Template : ct.Template }
I think this might work, although this is untested, from reading it appears you can't add multiple join conditions to a LinQ statement so you can just specify it in the where clause
So here ya go, I tried to convert the SQL word for word so here's my attempt. If it does everything I think it will do it will work.
int templateTypeId;
templateTypeId= (context.QuoteType.Where(x => x.QuoteTypeId == 7)).FirstOrDefault().TemplateTypeId
var qry =(
from t in context.Template
join ct in context.ClientTemplate on
t.TemplateTypeId equals ct.TemplateTypeId into cts
from ct in cts.DefaultIfEmpty() //left join
where t.TemplateTypeId == templateTypeId
&& ct.ClientId == 149
order by t.Version descending, ct.Version descending
select new
{
Template = (ct.Template != null) ? ct.Template : t.Template //ternary operator
}).FirstOrDefault();
I have the following query:
var query =
from modules in _Context.Modules
join moduleStrings in _Context.ModuleStrings on modules.MID equals moduleStrings.MID
join strings in _Context.Strings on moduleStrings.SID equals strings.SID
join stringTexts in _Context.StringTexts on strings.SID equals stringTexts.SID into stringsEmpty
from stringTexts in stringsEmpty.DefaultIfEmpty()
join languages in _Context.Languages on stringTexts.LID equals languages.LID
where modules.MID == MID && LID == languages.LID
select new GridData6S()
{
Name = strings.Name,
Text = stringTexts != null ? stringTexts.Text : ""
};
I want to join it so that I see the empty text if stringTexts is null.
It's probably some small thing, but I have been looking at this for an hour and can't figure it out. This is the closest I got.
You are filtering out any language that is not LID=languages.LID so when languages/stringTexts are null this condition will never be true.
Also as the only reason you seem to be joining to the languages table is to get the LID which is also the join condition, you could just skip joining to languages
The same is true for modules.....
This might help and is a little simpler
var query =
from moduleStrings in _Context.ModuleStrings
join strings in _Context.Strings on moduleStrings.SID equals strings.SID
join stringTexts1 in _Context.StringTexts.Where(x=>x.LID==LID) on strings.SID equals stringTexts.SID into stringsEmpty
from stringTexts in stringsEmpty.DefaultIfEmpty()
where moduleStrings.MID == MID
select new GridData6S()
{
Name = strings.Name,
Text = stringTexts != null ? stringTexts.Text : ""
};
I have following query, and I am converting it to LINQ.
select acq.ACQPub as Prev_ACQPub
, ve.CompanyID
, ve.EntityID
, ve.RoundID
, ve.EntityName
, ve.Date
, ve.RoundTypeCode
, ve.EventType
, ve.PostValue_DJVS
, ve.PostVal
, ve.PreVal
, fin.FinanceStat
from ValuationEvents_PIT_New as ve
left join Acq_PublicDummy as acq
on ve.EntityID = acq.EntityID
left join FinStat_New as fin
on ve.EntityID = fin.EntityID
where ve.EventType in('ACQ','LBO')
and acq.ACQPub is null
I wanted to double check if I've done it right or there is a better way of doing it.
Here is my code:
return (from ve in valuationEvents where ve.EventType == EventTypes.Acq || ve.EventType == EventTypes.Lbo
join acq in acqPublicDummies on ve.EntityId equals acq.EntityID into veAcq
from x in veAcq.DefaultIfEmpty() where x != null && x.ACQPub == null
join fin in finStats on ve.EntityId equals fin.EntityID into veFin
from y in veFin.DefaultIfEmpty()
select new AcqResearch
{ PrevAcqPub = x == null ? null : x.ACQPub,
EntityId = ve.EntityId,
CompanyId = ve.CompanyId,
RoundId = ve.RoundId,
Date = ve.Date,
RoundTypeCode = ve.RoundTypeCode,
EventType = ve.EventType.ToString(),
PostValueDjvs = ve.PostMoneyValue,
PostVal = ve.PostVal,
PreVal = ve.PreVal,
FinanceStat = y == null ? null : y.FinanceStat
}).ToList();
Since result will be used > 1 times I am returning List instead of IEnumerable.
Also I can't run SQL and compare result of it with LINQ result, since query above runs against of Raw data and LINQ is running after data calculations and additional cleansing process. So there is no way for me to compare query result with my LINQ result. I just need to rely that logic is correct. What is the same is SQL logic and LINQ logic.
Thank you very much for your help and feedback!
If you want to verify that the query is the same, you can look at the SQL that is generated from the linq. there are a few ways of doing this:
Use SQL Profiler
Paste the query into LinqPad and view the SQL tab
Set the Log property on your datacontext
You can then compare the two SQL queries and check for differences.
As an aside, in your case the only things I would change are style related - I would move all of the where clauses to just above the select clause, so it is easier to see what filter you are applying. Also, the line
PrevAcqPub = x == null ? null : x.ACQPub
Seems like it may as well be
PrevAcqPub = null
Since you have already filtered out all x that are null and that have x.ACQPub != null (Same goes for the SQL query).
Your solution looks correct to me