Linq Select Data based on a value in another table - c#

I have the linq statements listed below and I want to restrict the records from one table based on the value in another table. This is the code I have which works:
using (context = new DocEntityConnection())
{
var Docs = context.tbDocsDetails.Where(md => md.IsCurrentDetails && md.tbDoc.StatusID == 9).ToList();
this.approves = context.tbDocApproves.ToList().Where(a => Docs.Select(x => x.DocID).ToList().Contains(a.DocID)).ToList();
return Docs.Select(md => GetDataItem(md)).ToList();
}
There is another table called tbDocStatus which has a DocId field too
I would like to only return records from tbDocDetails where tbDocdetails.DocId = tbDocStatus.DocId and tbDocStatus.StatusId = 4.
How would I add that to my code shown above?

That you need is a join
var Docs = from docDetail in context.tbDocsDetails
join docStatus in context.tbDocStatus
on docDetail.DocId = docStatus.DocId
where docStatus.StatusId == 4
select docDetail;

using (context = new DocEntityConnection())
{
var Docs = context.tbDocsDetails.Where(md => md.IsCurrentDetails && md.tbDoc.StatusID == 9).ToList();
var DocsFiltered = from d in Docs
join docStatus in context.tbDocStatus
on d.DocId equals docStatus.DocId
where docStatus.StatusId = 4
select d
this.approves = context.tbDocApproves.ToList().Where(a => Docs.Select(x => x.DocID).ToList().Contains(a.DocID)).ToList();
return DocsFiltered.Select(md => GetDataItem(md)).ToList();
}

Related

Join List Data from two separate Data Contexts

I have been searching for the solution to this problem and this is what I have so far:
var ProductInfo = (from p in twd.Products
orderby p.PC
where p.DELMARK == active
select p).AsEnumerable();
var BuyersData =
(from x in db.MinimumProductInfo
where x != null
orderby x.ItemCode, x.Region
let pnote =
(from pn in db.ProductNotes
where pn != null
where x.MinimumProductInfoID == pn.MinimumProductInfoID
&& pn.NoteTypeFlag == "p"
orderby pn.NoteDate descending
select pn).FirstOrDefault()
let cnote =
(from c in db.ProductNotes
where c != null
where x.MinimumProductInfoID == c.MinimumProductInfoID
&& c.NoteTypeFlag == "c"
orderby c.NoteDate descending
select c).FirstOrDefault()
let product =
(from p in ProductInfo
where x.ItemCode == p.PC
select p).FirstOrDefault()
select new ProductInfoWithNoteList
{
MinimumProductInfoID = x.MinimumProductInfoID,
ItemCode = x.ItemCode,
EquivCode = x.EquivCode,
Description = product.PDESC,
MinimumOnHandQuantity = x.MinimumOnHandQuantity,
MaximumOHandQuantity = x.MaximumOHandQuantity,
MinimumOrderQuantity = x.MinimumOrderQuantity,
LeadTimeInWeeks = x.LeadTimeInWeeks,
Region = x.Region,
Comment = cnote.ItemNote,
PermanentNote = pnote.ItemNote
}).ToArray();
It looks correct but I am getting an error,
'The specified LINQ expression contains references to queries that are
associated with different contexts.'
What this code is supposed to do is pull out all the active product codes from the first table using the twd datacontext then use data from that database in the db.MinimumProductInfo table. The reason they have 2 separate data contexts are they are completely different databases, the first is our ERP and the second is one that we are building in house.
What am I missing? I know it is possible to do this by separating the two datacontexts then adding them together because I have seen it done with single instances but I cannot find how to do it with list data.
Instead of this:
let product =
(from p in ProductInfo
where x.ItemCode == p.PC
select p).FirstOrDefault()
select new ProductInfoWithNoteList
{
MinimumProductInfoID = x.MinimumProductInfoID,
ItemCode = x.ItemCode,
EquivCode = x.EquivCode,
Description = product.PDESC,
MinimumOnHandQuantity = x.MinimumOnHandQuantity,
MaximumOHandQuantity = x.MaximumOHandQuantity,
MinimumOrderQuantity = x.MinimumOrderQuantity,
LeadTimeInWeeks = x.LeadTimeInWeeks,
Region = x.Region,
Comment = cnote.ItemNote,
PermanentNote = pnote.ItemNote
}).ToArray();
Try this by removing the let product clause and not filling the properties associated with ProductInfo because we will do that afterwards (See I have commented out the Description property):
select new ProductInfoWithNoteList
{
MinimumProductInfoID = x.MinimumProductInfoID,
ItemCode = x.ItemCode,
EquivCode = x.EquivCode,
//Description = product.PDESC,
MinimumOnHandQuantity = x.MinimumOnHandQuantity,
MaximumOHandQuantity = x.MaximumOHandQuantity,
MinimumOrderQuantity = x.MinimumOrderQuantity,
LeadTimeInWeeks = x.LeadTimeInWeeks,
Region = x.Region,
Comment = cnote.ItemNote,
PermanentNote = pnote.ItemNote
}).ToArray();
Now that you have your BuyersData and ProductInfo in memory, set the Description property or all the items in BuyersData:
foreach(var thisBuyerData in BuyersData)
{
var thisPi = ProductInfo.SingleOrDefault(x => x.PC == thisBuyerData.ItemCode);
thisBuyerData.Description = thisPi?.PDESC;
}

Entity Framework - convert LINQ method chain with SelectMany to query syntax

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)

NHibernate - Inner Join between different sessions (different connections)

two different projects I want INNER JOIN statement to write out.
Include the second session of the results, but I can not get
using (ISession session = Con1.OpenSessiongeneral())
{
using (ISession session1 = Con2.OpenSessionsystem())
{
result = (from s in session.Query<AU_SalesTarget>()
join t in session.Query<AU_Terms>() on s.termId equals t.termId
join b in session1.Query<Branchs>() on s.branchId equals b.branchId
select new SalesTarget_Derogate
{
salesTargetId = s.salesTargetId,
mounth = t.month,
year = t.year,
calculateMethod = s.calculateMethod,
branchName = b.branchName
}).Skip(0).Take(50).ToList<SalesTarget_Derogate>();
}
}
list returns null
Im not sure why you get a null list, but you should use a store procedure if your SQL Server instance, support the join between different instances.
If is not supported, the solution is not elegant, you can try to get the data first, then use linq to join them like this:
using (ISession session = Con1.OpenSessiongeneral())
{
result = (from s in session.Query<AU_SalesTarget>()
join t in session.Query<AU_Terms>() on s.termId equals t.termId
select new
{
salesTargetId = s.salesTargetId,
mounth = t.month,
year = t.year,
calculateMethod = s.calculateMethod,
branchId = s.branchId
})
.Skip(0)
.Take(50)
.ToList();
}
var branchIds = result.Select(x => x.branchId)
.List();
Branchs bAlias = null;
IList<Branchs> branches = null;
using (ISession session1 = Con2.OpenSessionsystem())
{
branches = session1.QueryOver<Branchs>
.WhereRestrictionOn(x => x.branchId).IsIn(branchIds)
.Select(list => list
.Select(x => x.branchId).WithAlias(() => bAlias.branchId)
.Select(x => x.branchName).WithAlias(() => bAlias.branchName)
)
.TransformUsing(Transformers.AliasToBean<Branchs>())
.List<Branchs>();
}
result = result.Join(branches,
x => x.branchId,
x => x.branchId,
(x, y) => new SalesTarget_Derogate
{
salesTargetId = x.salesTargetId,
mounth = x.month,
year = x.year,
calculateMethod = x.calculateMethod,
branchName = y.branchName
}).ToList();

Check if data returned from sql table contains decimal list values in linq?

I want to return only those data from sql table which contains specific values from list.How can i do that ?
List<decimal> userHeirarchyId = new List<decimal>();
List<decimal> userGroupId = new List<decimal>();
//Get groups based on user
string userGroupIds = (from ucp in db.UserControlPrivileges
where ucp.UserId == (decimal)AMSECSessionData.userId
select ucp.GroupIds).FirstOrDefault().ToString();
userGroupId = userGroupIds.Split(',').Select(x => decimal.Parse(x)).ToList();
//Get heirarchy based on company and usergroup
userHeirarchyId = db.Groups
.Where(x=>x.Hierarchy.CompanyId==(decimal)AMSECSessionData.companyId
=>stuck here && x.GroupId.contains(userGroupIds ))
Any help will be appreciated..
Try this. Change the order how you're using Contains like 'your compare list'.Contains(member name)
var userHeirarchyId = db.Groups
.Where(x=> x.Hierarchy.CompanyId == (decimal)AMSECSessionData.companyId
&& userGroupIds.Contains(x.GroupId))
Write it like this :
var user = db.UserControlPrivileges.FirstOrDefault(u =>
u.UserId == (decimal)AMSECSessionData.userId);
if(user == null || user.GroupIds == null)
{
return;
}
var userIds = user.GroupIds.Split(',').Select(x => decimal.Parse(x)).ToList();
And then :
var userHeirarchyId = db.Groups
.Where(x => x.Hierarchy.CompanyId==(decimal)AMSECSessionData.companyId
&& userIds.Contains(x => x.GroupId));

Joining two tables in linq method syntax, MVC EntityFramework

I'm working with two tables: CI_CLIENTRISK (SCD type 2)... and QB_INVOICES_HEADER (edmx screenshot).
They can be joined via ClientID. I want to essentially replicate this query:
SELECT a.ClientID,
MAX(b.InvoiceDt) AS MaxInvoiceDt
(omitted for brevity)
FROM CI_CLIENTRISKADJS a
INNER JOIN QB_INVOICES_HEADER b
ON a.ClientID = b.ClientID
WHERE a.IsActive = 1
GROUP BY a.ClientID
ORDER BY MaxInvoiceDt DESC
Here's what I have so far. It's not returning any records.
using (var db = new PLOGITENS01Entities())
{
var rvClientRiskAdjs = db.CI_CLIENTRISKADJS
.Take(50)
.Join(db.QB_INVOICES_HEADER,
a => a.ClientID,
b => b.ClientID,
(a, b) => new { Risk = a, Invoices = b })
.Where(a => a.Risk.IsActive == 1)
.OrderByDescending(o => o.Invoices.InvoiceDt)
.Select(c => new ClientRiskModel()
{
ClientRiskId = c.Risk.ClientRiskID,
ClientName = c.Risk.CI_CLIENTLIST.ClientName,
ClientId = c.Risk.ClientID,
ClientRiskAdjs = c.Risk.ClientRiskAdjs,
RecordValidStartDt = c.Risk.RecordValidStartDt,
RecordValidEnddt = c.Risk.RecordValidEnddt,
IsActive = c.Risk.IsActive
})
.ToList();
return View(new GridModel(rvClientRiskAdjs));
}
Try putting your .Take(50) method after your final .Select and before .ToList(). As it is, you are only taking the first 50 records of the first table and then joining from there. I'm assuming that there are no joins to the second table in the first 50 records of the first table; therefore, your result will have 0 records.
I stumbled across this solution from reading this post: https://stackoverflow.com/a/157919/1689144
var rvClientRiskAdjs = (from ri in db.CI_CLIENTRISKADJS
join qb in
(from qb in db.QB_INVOICES_HEADER
orderby qb.InvoiceDt ascending
group qb by qb.ClientID into grp
select new
{
InvoiceDt = grp.Max(s => s.InvoiceDt),
ClientID = grp.Key
})
on ri.ClientID equals qb.ClientID
orderby qb.InvoiceDt descending
where ri.IsActive == 1
select new ClientRiskModel()
{
ClientRiskId = ri.ClientRiskID,
ClientName = ri.CI_CLIENTLIST.ClientName,
ClientId = ri.ClientID,
ClientRiskAdjs = ri.ClientRiskAdjs,
RecordValidEnddt = ri.RecordValidEnddt,
RecordValidStartDt = ri.RecordValidStartDt
})
.ToList();

Categories

Resources