Linq query equivalent of exists with multiple conditions - c#

I've been using linq for a little while now but haven't come across this situation anywhere and my google-fu let me down.
Basically I have two data sets which I did not define and now have to use to return data.
class Header
{
string COMPANY_CODE
string REFERENCE_NBR
string REFERENCE_DUPLICATE
...
}
class Line
{
string COMPANY_CODE
string REFERENCE_NBR
string REFERENCE_DUPLICATE
string STOCK_CODE
string DESCRIPTION
...
}
From a database perspective they join like this
select *
from Header
inner join Line
on header.COMPANY_CODE = Line.COMPANY_CODE
and header.REFERENCE_NBR = Line.REFERNCE_NBR
and header.REFERENCE_DUPLICATE = LINE.REFERENCE_DUPLICATE
and have a 1:Many relationship.
I'm implementing a search feature for a listing that is meant to find any Lines that with a value in STOCK_CODE or DESCRIPTION that matches a given search term. I have seen a couple of methods of joining using a linq query but because of the multiple join conditions I'm a bit lost and have not found any examples of what I'm trying to do.
If I were to write the statement I am trying to get in lamda/linq in SQL it would be:
declare #searchtxt nvarchar(max) = 'test'
Select *
from header h
where exists (
select *
from Line l
where
(
l.stock_code like '%'+#searchtxt+'%'
or l.description like '%'+#searchtxt+'%'
)
and h.COMPANY_CODE = l.COMPANY_CODE
and h.REFERENCE_NBR = l.REFERENCE_NBR
and h.REFERENCE_DUPLICATE = l.REFERENCE_DUPLICATE
)
Any help would be appreciated!

Perhaps, this?
var result = header.Where(h =>
Line.Any(l => (l.stock_code.Contains(searchtxt)
|| l.description.Contains(searchtxt))
&& h.COMPANY_CODE == l.COMPANY_CODE
&& h.REFERENCE_NBR == l.REFERENCE_NBR
&& h.REFERENCE_DUPLICATE == l.REFERENCE_DUPLICATE));

This is a traditional LINQ query for better understanding,
string searchtext = "";
var result = (from h in context.Headers
join l in context.Lines on new { h.COMPANY_CODE, h.REFERENCE_DUPLICATE, h.REFERENCE_NBR } equals new { l.COMPANY_CODE, l.REFERENCE_DUPLICATE, l.REFERENCE_NBR }
where l.STOCK_CODE.Contains(searchtext) || l.DESCRIPTION.Contains(searchtext)
select new
{
COMPANY_CODE = h.COMPANY_CODE,
STOCK_CODE = l.STOCK_CODE
//You can select more fields from "h" and "l"
}).ToList();
Edit:
string searchtext = "";
var result = (from h in context.Headers
join l in context.Lines on new { h.COMPANY_CODE, h.REFERENCE_DUPLICATE, h.REFERENCE_NBR } equals new { l.COMPANY_CODE, l.REFERENCE_DUPLICATE, l.REFERENCE_NBR }
where l.STOCK_CODE.Contains(searchtext) || l.DESCRIPTION.Contains(searchtext)
select h
)
.GroupBy(x => new { x.COMPANY_CODE, x.REFERENCE_DUPLICATE, x.REFERENCE_NBR })
.Select(x => x.First())
.ToList();

db.Header.Join(
db.Line,
h => new { h.COMPANY_CODE, h.REFERENCE_NBR, h.REFERENCE_DUPLICATE },
l => new { l.COMPANY_CODE, l.REFERENCE_NBR, l.REFERENCE_DUPLICATE },
(h, l) => new
{
Header_COMPANY_CODE = h.COMPANY_CODE,
Header_REFERENCE_NBR = h.REFERENCE_NBR,
Header_REFERENCE_DUPLICATE = h.REFERENCE_DUPLICATE,
Line_Company_Code = l.COMPANY_CODE,
Line_REFERENCE_NBR = l.REFERENCE_NBR,
Line_REFERENCE_DUPLICATE = l.REFERENCE_DUPLICATE,
Line_STOCK_CODE = l.STOCK_CODE,
Line_DESCRIPTION = l.DESCRIPTION
}
)
.Where(w => w.Line_STOCK_CODE.Contains(searchText) || w.Line_DESCRIPTION.Contains(searchText))
.ToList();

Related

Linq to SQL grouping with embedded lists causes too many queries

I am developing a query to grab and join some SQL tables in C# and am having some trouble with grouping and enumerables within the dataset. My query is below. This gives me the data in the format I'm looking for, but it takes way too long when I try to add the enumerated list as indicated below. When I look under the hood I can see it is executing way too many SQL queries. I'd like to get it to just one. Using LinqPad:
void Main()
{
var nightlyRuns = (from a in LoadTestSummaries
join b in LoadTestTestSummaryData
on a.LoadTestRunId equals b.LoadTestRunId
where a.TargetStack == "LoadEnv" &&
a.TestGuid != null &&
a.StartTime != null &&
a.LoadTestRunId != null
orderby a.StartTime
group new {a, b} by new
{
a.TestGuid,
a.Name,
a.Description,
a.StartTime,
a.Duration,
a.NumAgents,
a.NumHosts,
a.PassFail,
a.ResultsFilePath,
a.Splunk
}
into g
let scenarioStart = g.Min(s => s.a.StartTime) ?? g.Min(s => s.a.DateCreated)
let testCases = g.Select(s => s.b)
orderby scenarioStart
select new
{
TestGuid = g.Key.TestGuid,
ScenarioRun = new
{
Name = g.Key.Name,
Description = g.Key.Description,
StartTime = scenarioStart,
Duration = g.Key.Duration,
NumAgents = g.Key.NumAgents,
NumHosts = g.Key.NumHosts,
Result = g.Key.PassFail,
ResultsFilePath = g.Key.ResultsFilePath,
SplunkLink = g.Key.Splunk,
// PROBLEM: Causes too many queries:
TestRuns = from t in testCases select t.TestCaseId
}
}).ToLookup(g => g.TestGuid, g => g.ScenarioRun);
nightlyRuns["ba593f66-695f-4fd1-99c3-71253a2e4981"].Dump();
}
The "TestRuns" line is causing the excessive queries. Any idea what I am doing wrong here?
Thanks for any insight.
Tough answer to test but I think we can avoid the grouping and multiple queries with something like this: (https://msdn.microsoft.com/en-us/library/bb311040.aspx)
var nightlyRuns = (from a in LoadTestSummaries
join b in LoadTestTestSummaryData
on a.LoadTestRunId equals b.LoadTestRunId
where a.TargetStack == "LoadEnv" &&
a.TestGuid != null &&
a.StartTime != null &&
a.LoadTestRunId != null
into testGroup
select new
{
TestGuid = a.TestGuid,
ScenarioRun = new
{
Name = a.TestGuid,
Description = a.Description,
StartTime = a.StartTime ?? a.DateCreated,
Duration = a.Duration,
NumAgents = g.Key.NumAgents,
NumHosts = a.NumHosts,
Result = a.PassFail,
ResultsFilePath = a.ResultsFilePath,
SplunkLink = a.Splunk,
// PROBLEM: Causes too many queries:
TestRuns =testGroup
}
}).OrderBy(x=>x.StartTime).ToLookup(x => x.TestGuid, x => x.ScenarioRun);
nightlyRuns["ba593f66-695f-4fd1-99c3-71253a2e4981"].Dump();

To many nested statements

I have a c# code as follows
var deptSalesQuery =
from d in db.DashboardFigures
join s in outlets.Split(',').Select(x => int.Parse(x)) on d.OutletNo equals s
where (d.TypeOfinformation == "SALES")
group d by new
{
d.Number
} into newGroupedresult
select new DeptSales()
{
Dn = (int)newGroupedresult.Key.Number,
Qs = (double)newGroupedresult.Sum(d => d.Value_4),
Se = (double)newGroupedresult.Sum(d => d.Value_2),
Si = (double)newGroupedresult.Sum(d => d.Value_3)
+ (double)newGroupedresult.Sum(d => d.Value_2)
};
When I pass in Outlets = "1,2,3,4,....all the way upto 110", the software crashes telling me that there are too many nested statements.
Is there any way that I can remove the JOIN and add something onto the WHERE clause to help the situation?
Thanks
As written by juharr, before the query do:
int[] splitted = outlets.Split(',').Select(int.Parse);
and in the query:
where splitted.Contains(d.OutletNo) && d.TypeOfinformation == "SALES"

Converting SQL to linq with a right join (advanced)

I have the following SQL statement:
SELECT dh.*
FROM table1 w
LEFT OUTER JOIN table2 dh
on w.CBranch = dh.CBranch
AND w.CWorkstation = dh.CWorkstation
AND w.CNumber = dh.CNumber
RIGHT OUTER JOIN table3 dl
on dh.Id = dl.DispatchHeaderId
AND w.CLine = dl.CLine
AND w.CLineVersion = dl.CVersion
where w.ItemStatus = 9
AND dh.Shipping = 0
ORDER BY dh.CNumber ASC
I am beginner in Linq and not sure how to do advanced linq.
Could someone please guide me writing equivalent linq for this.
I am using C#, EF4.
I have managed to get till here, but not sure f this is correct.
var wos = scope.Context.table1.Where(
a => a.ItemStatus == (short)LineStatus.Packed)
.GroupBy(a => new { a.CNumber, a.CBranch, a.CWorkstation})
.Select(a => a.FirstOrDefault()).ToList();
var headerGroups = new List<IEnumerable<table2>>();
foreach(var status in wos)
{
if (status == null)
{
continue;
}
var headerList = scope.Context.table2s.Where(
b => b.CBranch == status.CBranch &&
b.CNumber == status.CNumber &&
b.CWorkstation == status.CWorkstation).ToList();
if (headerList != null && headerList.Any())
{
headerGroups.Add(headerList);
}
};
use defaultifemty() method in following link way....
http://smehrozalam.wordpress.com/2009/06/10/c-left-outer-joins-with-linq/

Linq to select data from one table not in other table

Hi i have the following code to select data from one table not in other table
var result1 = (from e in db.Users
select e).ToList();
var result2 = (from e in db.Fi
select e).ToList();
List<string> listString = (from e in result1
where !(from m in result2
select m.UserID).Contains(e.UserID)
select e.UserName).ToList();
ViewBag.ddlUserId = listString;
Am getting value inside listString .But got error while adding listString to viewbag.
Unable to cast object of type 'System.Collections.Generic.List`1[System.String]' to type 'System.Collections.Generic.IEnumerable`1[Main.Models.Admin.User]'.
First, could you update your question with the entire method so that we can see what might be going on with the ViewBag? Because your code should work just fine, assigning whatever value to the ViewBag is no problem normally:
ViewBag.property1 = 0;
ViewBag.property1 = "zero";
works just fine. ViewBag is dynamic. Now, you could get that error if you would later try to assing ViewBag.ddlUserId to something that actually is the wrong type.
I would like you to rewrite your statement as well, let me explain why. Assume for a moment that you have a lot ( > 100.000) of User records in your db.Users and we assume the same for Fi as well. In your code, result1 and result2 are now two lists, one containing >100.000 User objects and the other >100.000 Fi objects. Then these two lists are compared to each other to produce a list of strings. Now imagine the resource required for your web server to process this. Under the assumption that your actually using/accessing a separate SQL server to retrieve your data from, it would be a lot better and faster to let that server do the work, i.e. producing the list of UserID's.
For that you'd either use Kirill Bestemyanov's answer or the following:
var list = (from user in db.Users
where !db.Fi.Any(f => f.UserID == user.UserID)
select user.UserName).ToList()
This will produce just one query for the SQL server to execute:
SELECT
[Extent1].[UserName] AS [UserName]
FROM [dbo].[Users] AS [Extent1]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Fi] AS [Extent2]
WHERE [Extent2].[UserID] = [Extent1].[UserID]
)}
which in the end is what you want...
Just to clarify more:
var list = (from user in db.Users
where !db.Fi.Any(f => f.UserID == user.UserID)
select user.UserName).ToList()
can be written as the following lambda expression as well:
var list = db.Users.Where(user => !db.Fi.Any(f => f.UserID == user.UserID))
.Select(user => user.UserName).ToList()
which from the looks of it is slightly different from Kirill Bestemyanov's answer (which I slightly modified, just to make it look more similar):
var list = db.Users.Where(user => !db.Fi.Select(f => f.UserID)
.Contains(user.UserID))
.Select(user => user.UserName).ToList();
But, they will in fact produce the same SQL Statement, thus the same list.
I will rewrite it to linq extension methods:
List<string> listString = db.Users.Where(e=>!db.Fi.Select(m=>m.UserID)
.Contains(e.UserID))
.Select(e=>e.UserName).ToList();
try it, it should work.
Try this it is very simple.
var result=(from e in db.Users
select e.UserID).Except(from m in db.Fi
select m.UserID).ToList();
var res = db.tbl_Ware.where(a => a.tbl_Buy.Where(c => c.tbl_Ware.Title.Contains(mtrTxtWareTitle.Text)).Select(b => b.Ware_ID).Contains(a.ID));
This mean in T-SQL is:
SELECT * FROM tbl_Ware WHERE id IN (SELECT ware_ID, tbl_Buy WHErE tbl_Ware.title LIKE '% mtrTxtwareTitle.Text %')
getdata = (from obj in db.TblManageBranches
join objcountr in db.TblManageCountries on obj.Country equals objcountr.iCountryId.ToString() into objcount
from objcountry in objcount.DefaultIfEmpty()
where obj.IsActive == true
select new BranchDetails
{
iBranchId = obj.iBranchId,
vBranchName = obj.vBranchName,
Addressline1 = obj.Addressline1,
Adminemailid = obj.Adminemailid,
BranchType = obj.BranchType,
Country = objcountry.vCountryName,
CreatedBy = obj.CreatedBy,
CreatedDate = obj.CreatedDate,
iArea = obj.iArea,
iCity = obj.iCity,
Infoemailid = obj.Infoemailid,
Landlineno = obj.Landlineno,
Mobileno = obj.Mobileno,
iState = obj.iState,
Pincode = obj.Pincode,
Processemailid = obj.Processemailid,
objbranchbankdetails = (from objb in db.TblBranchesBankDetails.Where(x => x.IsActive == true && x.iBranchId == obj.iBranchId)
select new ManageBranchBankDetails
{
iBranchId = objb.iBranchId,
iAccountName = objb.iAccountName,
iAccountNo = objb.iAccountNo,
iBankName = objb.iBankName,
iAccountType = objb.iAccountType,
IFSCCode = objb.IFSCCode,
SWIFTCode = objb.SWIFTCode,
CreatedDate = objb.CreatedDate,
Id = objb.Id
}).FirstOrDefault(),
objbranchcontactperson = (from objc in db.tblbranchcontactpersons.Where(x => x.Isactive == true && x.branchid == obj.iBranchId)
select new ManageBranchContactPerson
{
branchid = objc.branchid,
createdate = objc.createdate,
Id = objc.Id,
iemailid = objc.iemailid,
ifirstname = objc.ifirstname,
ilandlineno = objc.ilandlineno,
ilastname = objc.ilastname,
imobileno = objc.imobileno,
title = objc.title,
updateddate=objc.updateddate,
}).ToList(),
}).OrderByDescending(x => x.iBranchId).ToList();
getdata = (from obj in db.TblManageBranches join objcountr in db.TblManageCountries on obj.Country equals objcountr.iCountryId.ToString() into objcount from objcountry in objcount.DefaultIfEmpty() where obj.IsActive == true
select new BranchDetails
{
iBranchId = obj.iBranchId,
vBranchName = obj.vBranchName,
objbranchbankdetails = (from objb in db.TblBranchesBankDetails.Where(x => x.IsActive == true && x.iBranchId == obj.iBranchId)
select new ManageBranchBankDetails
{
iBranchId = objb.iBranchId,
iAccountName = objb.iAccountName,
}).FirstOrDefault(),
objbranchcontactperson = (from objc in db.tblbranchcontactpersons.Where(x => x.Isactive == true && x.branchid == obj.iBranchId)
select new ManageBranchContactPerson
{
branchid = objc.branchid,
createdate = objc.createdate,
Id = objc.Id,
iemailid = objc.iemailid,
}).ToList(),
}).OrderByDescending(x => x.iBranchId).ToList();

How Convert this T-SQL to LINQ

I have the following SQL statement
SELECT [CodeHouse]
,[CodeReq]
,[Address]
FROM [ShahrdariProject].[dbo].[House]
where [CodeReq] in
(select [CodeReq] From [ShahrdariProject].[dbo].[HouseOwner] where [Name] = 'Alex' )
Can anyone please help me to convert this statement to LINQ?
This SQL:
SELECT [CodeHouse]
,[CodeReq]
,[Address]
FROM [ShahrdariProject].[dbo].[House]
where [CodeReq] in
(select [CodeReq] From [ShahrdariProject].[dbo].[HouseOwner]
where [Name] = 'Alex' )
Is equivalent to this Linq:
var q = from h in db.Houses
where db.HouseOwners.Any(x => x.Name == "Alex" && x.CodeReq == h.CodeReq)
select h;
using(var dbContext = new /**Your Linq DataContext class here**/())
{
var results = dbContext.House.Join(
dbContext.HouseOwner.Where(ho => ho.Name == "Alex"),
h => h.CodeReq,
ho => ho.CodeReq,
(h, ho) => select new { h.CodeHouse, h.CodeReq, h.Address }).ToArray();
}
EDIT: Based on your query, I figured it would be oK to express the query using a JOIN instead of using IN
List<string> codeReq = new List<string>();
using(DemoDataContext db = new DemoDataContext()){
var houses = from h db.Houses where codeReq.Contains(h.codeReq) selec h;
}
Try to use the following code, i am sure this resolve your issue
var result = from house in db.Houses
where db.HouseOwners.Any(z => z.Name == "Alex" && z.CodeReq == house.CodeReq)
select house;
Enjoy......

Categories