I've got this SQL statement that I'm trying to convert to linq:
SELECT i.*
FROM Issues i
WHERE IssueID IN (SELECT ChildIssueId
FROM LinkedIssues
WHERE IssueId = 28438)
OR IssueID IN (SELECT IssueId
FROM LinkedIssues
WHERE ChildIssueId = 28438)
Here's what the data in the table looks like:
So in the sql above, I get issues 19220, 28436, & 28440 back. Here's what I've tried with no luck:
var childIssues = (from i in Issues
join li in LinkedIssues
on i.IssueID equals li.IssueId
where (from li2 in LinkedIssues
where li.IssueId == 28438 || li.ChildIssueId == 28438
select li2).Contains(28438)
select new LinkedIssuesModel()
{
IssueID = li.ChildIssueId,
CustomerName = i.Room.Location.Customer.CustomerName,
LocationName = i.Room.Location.LocationName,
ReceivedDate = i.ReceivedDate,
IssueSummary = i.IssueSummary,
IssueDescription = i.IssueDescription
}).ToList();
I need to know how to convert SQL IN statements to linq. I have LinqPad but it doesn't convert it when I click the lambda button. I've also downloaded and tried Linqer but it throws an "Object not set to an instance Object" error.
Please try the following:
var childIssues = (from i in Issues
from li in LinkedIssues
where (li.IssueId == 28438 && li.ChildIssueId == i.IssueID)
|| (li.ChildIssueId == 28438 && li.IssueId == i.IssueID)
select new LinkedIssuesModel()
{
IssueID = li.ChildIssueId,
CustomerName = i.Room.Location.Customer.CustomerName,
LocationName = i.Room.Location.LocationName,
ReceivedDate = i.ReceivedDate,
IssueSummary = i.IssueSummary,
IssueDescription = i.IssueDescription
}).ToList();
EDIT: Fixed query to address li.ChildIssueId on the select.
You are not joining.
var childIssues = Issues.
Where(x => LinkedIssues.
Where(z => z.IssueId = 28438).
Select(z => z.ChildIssueId).
Contains(x.IssueID)
||
LinkedIssues.
Where(z => z.ChildIssueId = 28438).
Select(z => z.IssueId).
Contains(x.IssueID)
);
Related
I am trying converting sql query into LINQ but after write query unable to fetch record from resultset
SELECT T.ServiceOrderNo,T.STATUS, T.SubStatus,T.orderVersion,T.OrderDate
,#pid, T.EventID, 'FOI'
FROM #temp1 T
LEFT JOIN Tbl_Service_Order_Progress O ON T.ServiceOrderNo DATABASE_DEFAULT = O.ServiceOrderNo
AND O.PARENTID = #pid
AND O.ServiceOrderType = 'FOI'
WHERE O.ServiceOrderNo IS NULL
Above Query following I'm trying in LINQ
var lstInsertFOI = (from i in lstFOI
join j in lstSOP on i.fulfilmentOrderItemIdentifier equals j.ServiceOrderNo into res
from subRight in res.DefaultIfEmpty()
where subRight.ParentId == parentId && subRight.ServiceOrderNo == null && subRight.ServiceOrderType.Equals("FOI")
select new
{
ServiceOrderNo = subRight.ServiceOrderNo == null ? i.fulfilmentOrderItemIdentifier : subRight.ServiceOrderNo,
EventStatus = i.status,
EventSubStatus = i.subStatus,
OrderVersion = i.orderVersion,
EVENTRECEIVEDDATE = i.orderDate,
ParentId = parentId,
EventID = i.eventID,
ServiceOrderType = "FOI",
}).ToList();
above linq query does not fetch expected result, which should return number of records from lstFOI list, but returns no record. Is the linq query correct?
Let start with SQL query.
LEFT JOIN Tbl_Service_Order_Progress O
ON T.ServiceOrderNo = O.ServiceOrderNo
AND O.PARENTID = #pid AND O.ServiceOrderType = 'FOI'
is equivalent to
LEFT JOIN (SELECT * FROM Tbl_Service_Order_Progress
WHERE PARENTID = #pid AND ServiceOrderType = 'FOI') O
ON T.ServiceOrderNo = O.ServiceOrderNo
then
WHERE O.ServiceOrderNo IS NULL
means that the query is actually using anti-join, i.e. include all the records from the left side that do not have a matching records from the right side.
With all that in mind, the equivalent LINQ query should be like this:
var lstInsertFOI = (
from i in lstFOI
join j in lstSOP
.Where(e => e.ParentId == parentId && subRight.ServiceOrderType == "FOI")
on i.fulfilmentOrderItemIdentifier equals j.ServiceOrderNo into res
where !res.Any()
select new
{
ServiceOrderNo = i.fulfilmentOrderItemIdentifier,
EventStatus = i.status,
EventSubStatus = i.subStatus,
OrderVersion = i.orderVersion,
EVENTRECEIVEDDATE = i.orderDate,
ParentId = parentId,
EventID = i.eventID,
ServiceOrderType = "FOI",
}).ToList();
Doing some stuff linq left join query but facing some problem. Not able to get proper result following sql query need to convert into linq
INSERT INTO tbl_service_order_attributes_versioning(ServiceOrderNo, AttributeId, AttributeValue, parentid, AttributeType, Dt_Stamp, VERSION)
SELECT
T.ServiceOrderNo, T.COIID, T.COI_Identifier,
#pid, 'MBM', getDate(), #ORDERVERSION
FROM
#temp1 T
LEFT JOIN
tbl_service_order_attributes_versioning O WITH(NOLOCK)
ON T.ServiceOrderNo = O.ServiceOrderNo COLLATE database_default
AND T.COIID = O.AttributeID
AND O.PARENTID = #pid
WHERE
O.ServiceOrderNo IS NULL
I have converted this query into a Linq query:
var soiAttr = (from s in ctxParser.TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING
where s.ParentId == parentId
select s).ToList();
var resultJoinCOI = (from soaI in soiAttr
join iFoi in listFOI on soaI.ServiceOrderNo equals iFoi.fulfilmentOrderItemIdentifier
where iFoi.coiId == soaI.AttributeId &&
iFoi.parentId == parentId &&
soaI.ServiceOrderNo == null
select iFoi).ToList();
if (resultJoinCOI.Count > 0)
{
var listToInsert = (from item in resultJoinCOI
select new TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING
{
ServiceOrderNo = item.fulfilmentOrderItemIdentifier,
AttributeId = item.coiId,
AttributeValue = item.coiIdentifier,
ParentId = parentId,
AttributeType = "MBM",
DT_Stamp = DateTime.Now,
VERSION = orderVersion
});
ctxParser.TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING.AddRange(listToInsert);
ctxParser.SaveChanges();
}
The code is executed but result are not correct.
You need to use DefaultIfEmpty (https://msdn.microsoft.com/en-us/library/bb360179.aspx). Here's a reading from MSDN: https://msdn.microsoft.com/en-us/library/bb397895.aspx
In your case it would be something like:
var resultJoinCOI = (
from iFoi in listFOI
join soaI in soiAttr on iFoi.fulfilmentOrderItemIdentifier equals soaI.ServiceOrderNo into res
from subIFoi in res.DefaultIfEmpty()
where iFoi.coiId == soaI.AttributeId && iFoi.parentId == parentId && subIFoi == null
select iFoi).ToList();
Following code that execute successfully. and getting right result.
var soiAttr = (from s in ctxParser.TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING
where s.ParentId == parentId
select s).ToList();
var resultJoinCOI = (from iFoi in listFOI
join soaI in soiAttr on
new
{
ServiceOrderNo = iFoi.fulfilmentOrderItemIdentifier,
AttributeId = iFoi.coiId
}
equals new
{
ServiceOrderNo = soaI.ServiceOrderNo,
AttributeId = soaI.AttributeId
}
into res
from subFoi in res.DefaultIfEmpty()
select new
{
fulfilmentOrderItemIdentifier = iFoi.fulfilmentOrderItemIdentifier,
coiId = iFoi.coiId,
coiIdentifier = iFoi.coiIdentifier,
AttributeId = subFoi == null ? 0 : subFoi.AttributeId,
ParentId = subFoi == null ? parentId : subFoi.ParentId,
ServiceOrderNo = subFoi == null ? string.Empty: subFoi.ServiceOrderNo
});
if (resultJoinCOI != null)
{
if (resultJoinCOI.Count() > 0)
{
var listToInsert = (from item in resultJoinCOI
select new TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING
{
ServiceOrderNo = item.fulfilmentOrderItemIdentifier,
AttributeId = item.coiId,
AttributeValue = item.coiIdentifier,
ParentId = parentId,
AttributeType = "MBM",
DT_Stamp = DateTime.Now,
VERSION = orderVersion
});
ctxParser.TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING.AddRange(listToInsert);
ctxParser.SaveChanges();
}
}
In this way we can implement left join in linq. as per above SQL Query(see above sql statement).
I'd like to ask a following question.
I'm building a query which will return some details about stored email packages.
Relationships:
Packages 1-------N Addresses 1------N OutboundPackages
I would like to convert testOK query to expression syntax, specifically the following statement:
referenceGuids = pkg.PackageAddresses.SelectMany(s=>s.AddressOutboundPackages).Select(s=>s.Reference)
Complete example:
var test = (from stamp in IssuedStamps
join pkg in Packages.Include(i=>i.PackageAddresses) on stamp.Id equals pkg.IssuedStampId
join addr in Addresses on pkg.Id equals addr.Package_Id
join outb in OutboundPackages on addr.Id equals outb.Address_Id
where stamp.PortalUserId == "f31c2582-f663-4f2e-a9f7-d41ba138f86c" && stamp.Used
//I'd like to convert the following SelectMany LINQ method chain expression to query syntax
//let referenceGuids = pkg.PackageAddresses.SelectMany(s=>s.AddressOutboundPackages).Select(s=>s.Reference)
select new
{
StampId = stamp.Id,
RecipientEmail = pkg.PackageAddresses.FirstOrDefault(x => x.AddressType == 1).EmailAddress,
SenderEmail = pkg.PackageAddresses.FirstOrDefault(x => x.AddressType == 0).EmailAddress,
DateSent = pkg.ReceivedDate,
Remarks = stamp.Description,
Ref = referenceGuids,
Subject = pkg.Subject,
IsMassMailing = pkg.ProcessingPackageId == null || pkg.ProcessingPackageId == string.Empty
}
).ToList();
var testOK = (from stamp in IssuedStamps
join pkg in Packages.Include(i=>i.PackageAddresses.Select(s=>s.AddressOutboundPackages)).Include(i=>i.PackageAddresses) on stamp.Id equals pkg.IssuedStampId
where stamp.PortalUserId == "f31c2582-f663-4f2e-a9f7-d41ba138f86c" && stamp.Used
let referenceGuids = pkg.PackageAddresses.SelectMany(s=>s.AddressOutboundPackages).Select(s=>s.Reference)
select new
{
StampId = stamp.Id,
RecipientEmail = pkg.PackageAddresses.FirstOrDefault(x => x.AddressType == 1).EmailAddress,
SenderEmail = pkg.PackageAddresses.FirstOrDefault(x => x.AddressType == 0).EmailAddress,
DateSent = pkg.ReceivedDate,
Remarks = stamp.Description,
Ref = pkg.PackageAddresses.SelectMany(s => s.AddressOutboundPackages).Select(s => s.Reference),
Subject = pkg.Subject,
IsMassMailing = pkg.ProcessingPackageId == null || pkg.ProcessingPackageId == string.Empty
}
).ToList();
That's easy.
referenceGuids = pkg.PackageAddresses
.SelectMany(s => s.AddressOutboundPackages)
.Select(s => s.Reference)
goes to
referenceGuids = (from pa in pkg.PackageAddresses
from aop in pa.AddressOutboundPackages
select aop.Reference)
I have two linq queries, in the second query i use the first query as a sub query. Basically the first query does a groupby to return distinct rows of ContactID to use in the second query, which then does a groupby on idnumber to check for duplicates.
private IQueryable<Contact> GetDistinctContact()
{
IQueryable<Contact> query = (from contact in context.Contacts
where contact.EDITED.Equals(0)
&& contact.NOTACTIVE.Equals(false)
&& contact.ID > 10001
join client in context.Clients on new { ClientID = contact.ID, EDITED = 0, DELETED = false }
equals new { ClientID = client.ContactID, EDITED = client.EDITED, DELETED = client.DELETED }
join member in context.Members on new { MemberID = client.ID, EDITED = 0, DELETED = false }
equals new { MemberID = member.ClientID, EDITED = member.EDITED, DELETED = member.DELETED }
select contact);
return query.GroupBy(x => x.ID).Select(grp => grp.FirstOrDefault());
}
IQueryable<ContactDetailsViewModelPart> query = (from contact in GetDistinctContact()
where contact.IdNumber != null
&& !contact.IdNumber.Trim().Equals("")
&& contact.EDITED.Equals(0)
&& contact.NOTACTIVE.Equals(false)
&& contact.ID > 10001
group contact
by new ContactDetailsViewModelPart
{
IDNumber = contact.IdNumber,
LastName = contact.LastName
}
into idNumberGroup
where idNumberGroup.Count() > 1
select new ContactDetailsViewModelPart
{
IDNumber = idNumberGroup.Key.IDNumber,
LastName = idNumberGroup.Key.LastName
});
return query.ToList();
This is the error i get. I am using Firebird database.
Dynamic SQL Error
SQL error code = -104
Token unknown - line 19, column 9
APPLY
EF generates SQL with a cross apply on sub query. I know this is not supported in later versions of Firebird. Any alternatives to this?
I think the first query could be eliminated (I guess contact.ID is a primary key), and use something like this:
var query =
from contact in context.Contacts
where contact.IdNumber != null
&& !contact.IdNumber.Trim().Equals("")
&& contact.EDITED.Equals(0)
&& contact.NOTACTIVE.Equals(false)
&& contact.ID > 10001
&& context.Clients.Any(client =>
client.ContactID == contact.ID && client.EDITED == contact.EDITED && client.DELETED == contact.EDITED
&& context.Members.Any(member =>
member.ClientID == client.ID && member.EDITED == client.EDITED && member.DELETED == client.DELETED
)
)
group contact
by new ContactDetailsViewModelPart
{
IDNumber = contact.IdNumber,
LastName = contact.LastName
}
into idNumberGroup
where idNumberGroup.Count() > 1
select idNumberGroup.Key;
return query.ToList();
Normally Any would be translated to SQL EXISTS subquery, which in turn most of the databases will treat as INNER JOIN. Unfortunatlely I don't know if Firebird does that, but it's worth trying.
I am trying to convert below SQL query into Linq.
select eg.userid, eg.groupid, count(r.RID) as RecipientCount
from eg
join g on eg.groupid = g.groupid
join r on g.RID = r.RID
where eg.UserId = '7F813844-3B93-418E-8141-654082C4E37D'
and eg.IsDeleted = 0
and r.Isdeleted = 0
group by eg.groupid
Above query runs properly in SQL.
My Linq code is:
var v = from eml in dc.egs
join recpingroup in dc.g on eml.GroupID equals recpingroup.GroupID
where eml.aspnet_User.LoweredUserName.Equals(strUserName.ToLower())
&& !eml.IsDeleted
&& !recpingroup.r.IsDeleted
select new Info()
{
CreateDt = eml.CreateDt.ToShortDateString(),
UserId = eml.UserId.ToString(),
LastUpdateDt = eml.LastUpdateDt.ToShortDateString(),
Username = eml.aspnet_User.UserName,
GroupDescription = eml.GroupDescription,
GroupID = eml.GroupID.ToString().ToUpper(),
GroupName = eml.GroupName,
Count = dc.g.Count(r1 => r1.GroupID.Equals(eml.GroupID) && !r1.r.IsDeleted)
};
where dc is my DataContext.
But I am having problems in the last property i.e. Count is coming wrong. I want the counts of recipients from recpingroup.r as RecipientCount.
Also note that tables are linked in SQL internally by PK and FK references.
try following
Count = (from x in dc.g where(r1 => r1.GroupID.Equals(eml.GroupID) && !r1.r.IsDeleted) select x.g).count()