How to use condition in LINQ take() method - linq

How to join two tables and get the records based on the class B variable values
Class A
{
RecordID int {get;set;}
Name string {get;set;}
}
Class B
{
Name string {get;set;}
DataToPick int {get;set;}
}
My inputs are
Class A
---------------------
RecordID name
1 Sathish
2 Sathish
3 Kumar
4 Kumar
5 Ajay
Class B
--------------------------------------
Name DataToPick
Sathish 1
kumar 2
Now i want to join two tables and get the values from Class A i.e 3 records, based on the Class B variable (Datatopick)
Please help to write it in LINQ like below
var qry= (from c in classA
join d in ClassB on c.name equals d.name
select c).take(d.datatopick)

You can group ClassA and then select the DataToPick from the other list.
var result =
classA.GroupBy(a => a.Name)
.SelectMany(g => g.Take(classB.Where(b => b.Name == g.Key)
.Select(b => b.DataToPick)
.DefaultIfEmpty(0)
.Single()));
Even better join first and the take:
var result = classA.Join(classB, a => a.Name, b => b.Name, (a, b) => new {a, b.DataToPick})
.GroupBy(arg => new {arg.a.Name, arg.DataToPick})
.SelectMany(g => g.Select(arg => arg.a).Take(g.Key.DataToPick));

You could join classA and classB, group by Name, DataToPick and use Take like that
(from a in listA
join b in listB on a.Name equals b.Name
group new { a, b } by new { a.Name, b.DataToPick } into gr
select new
{
Name = gr.Key.Name,
ListA = gr.Select(x=>x.a).Take(gr.Key.DataToPick)
}
).SelectMany(x => x.ListA).ToList();

Related

How can I get the top categories by join in LINQ?

I am working on classified ads project I am facing problem to get top categories where most ads are posted every category have sub category also.
I made query but it is working for sub category ads I want if any category have no sub category then parent category ads should counted.
var result = (from c in db.Category
join a in db.Ad on c.CategoryId equals a.CategoryId
where c.ParentId != null
group c by c.ParentId into g
select new { cat = g.Key, a = g.Count() })
.OrderBy(c => c.cat)
.OrderByDescending(a => a.a);
My Category Table is like this
CategoryId ----- ParentId -----Name
How can I do this?
I guess this could be done with separate queries:
Get a list of categories that don't have any parentId set:
var resultsWithoutSubs = from c in db.Category
where c.ParentId == null
&& !result.Any(r => cat == c.CategoryId)
select c;
Based on the list above, repeat the original query:
var counts = from c in resultsWithoutSubs
join a in dbAd on c.CategoryId equals a.CategoryId
group c by c.CategoryId into g
select new {cat = g. Key, a = g.Count};
Then you should be able to Union these the first and the last list and sort the results.
Try this:
var results = db.Category
.Join(db.Ad, cat => cat.CategoryId,
ad => ad.CategoryId, (cat, ad) => new { cat, ad } )
.Where (c => !dbCategory
.Any (d => c.cat.CategoryId == d.ParentId) && c.cat.ParentId == null)
.GroupBy (c => c.cat.CategoryId)
.Select (g => new
{ cat = g.Key, a = g.Count () }
);

Can you make this Many to Many script more dynamic?

This is just my simple way of making a many to many relationship, but i would like something that makes it easy to create many to many, I have wished i could make a method return type anonymous, that would open some doors. But i am noot good with anonymous types, Yet!
Hope you can help !
What do you guys do when you need
private class Ids
{
public int Id;
}
.
...
. And in some method:
IList<Ids> objIds = new List<Ids>();
var q = from c in dt.FK_Tags_Blogs
where c.BlogId == someId
select c.TagId;
foreach (var item in q)
{
objIds.Add(new Ids { Id = item });
}
var w = from c in objIds
join p in dt.Tags on c.Id equals p.Id
select p;
David B: I Used your code like this:
public static IQueryable<Tag> printTags(int id)
{
DataClassesDataContext dt = new DataClassesDataContext();
return
from b in dt.Blogs
where b.Id == id
from xr in b.FK_Tags_Blogs
select xr.Tag;
}
Is that stupid?
What I do is:
//linq to objects
IEnumerable<Tag> tags =
from c in dt.FK_Tags_Blogs
where c.BlogId == someId
join p in dt.Tags on c.TagId equals p.Id
select p;
//linq to sql with association properties
IQueryable<Tag> tagsQuery =
from b in dc.Blogs
where b.BlogId == someId
from xr in b.FK_Tags_Blogs
select xr.Tag;

How to return specific list result from linq to entities

Hi Experts
I currenly write this code:
public IList<TResult> GetCustomQuery<TResult>(int orderID, Func<Order, TResult> selector)
{
using(RepositoryDataContext = new NorthwindEntities())
{
IList<TResult> res = (from od in RepositoryDataContext.Order_Details
join o in RepositoryDataContext.Orders
on od.OrderID equals o.OrderID
join p in RepositoryDataContext.Products
on od.ProductID equals p.ProductID
join c in RepositoryDataContext.Customers
on o.CustomerID equals c.CustomerID
where o.OrderID > orderID
select new
{
o.OrderID,
od.UnitPrice,
od.Quantity,
p.ProductName,
c.CompanyName
}).Select<Order, TResult>(selector).ToList();
}
}
I want to return result of my linq to entities in specific format(TResult).
writing this code using Lambda Expression is hard because of joins.
this line has exception :Select < Order, TResult > (selector)
how I can Fix that?
thanks
Instead of creating an Anonymous type, create a POCO or in your case an Order
select new Order()
{
OrderProperty1 = o.OrderID,
OrderProperty2 = od.UnitPrice,
OrderProperty3 = od.Quantity,
OrderProperty4 = p.ProductName,
OrderProperty5 = c.CompanyName
}).Select<Order, TResult>(selector).ToList();
In your second last line: Try to call ToList() before the Select(). Like this:
}).ToList().Select<Order, TResult>(selector);
Is it possible Iterate "res" and return a list of TResult?

LINQ Join With Multiple Where Clause

I am struggling once again so any help would be gratefully received.
I have the following LINQ that pulls back a list of data:
public static List<tblWeight> GetWeights(string memberid, string locationid, string buyer, string subcategory, string product)
{
MyEntity getweights = new MyEntity ();
var r = (from p in getweights.tblWeights
where p.MemberId == memberid &&
p.LocationId == locationid
select p);
if (buyer != "Not Specified")
r = r.Where(p => p.UnitUserField1 == buyer);
if (subcategory != "Not Specified")
r = r.Where(p => p.UnitUserField2 == subcategory);
if (product != "Not Specified")
r = r.Where(p => p.IDDesc == product);
return r.ToList();
}
Lovely!
What I would like to do now is based upon this result set and the unit IDs (IDDesc), I then go to tblPurchase, pull back a few columns from tblPurchases and group the columns.
So for example, we have tblWeight looking like so:
MemberID LocationID Buyer SubCategory IDDesc
1 1 Cat1 Sub1 ab
1 1 Cat1 Sub1 abc
1 1 Cat1 Sub2 abcd
The user makes a search for Sub1 in subcategory and the above LINQ does the trick and pulls back the first two rows from above. Fine.
What I need the LINQ to do now is to go to tblPurchases:
MemberID LocationID IDDesc SupplierID SupplierStatus
1 1 ab Sup1 Live
1 1 abc Sup1 Live
1 1 abcd Sup2 Dead
And then pull back the following result so it is joined on MemberID, LocationID and IDDesc but just selects tblPurchases.
Sup1 Live (or all columns in tblPurchases, just grouped/distinct)
I have tried to add in a join and on but no matter how many different variations, I still come across the red squiggle of doom!!!
If anyone can help, beer/kiss is on offer again.
The following LINQ query should do what you want:
var result = from w in tblWeight
where w.SubCategory == "Sub1"
join p in tblPurchases on
new { w.MemberID, w.LocationID, w.IDDesc } equals
new { p.MemberID, p.LocationID, p.IDDesc }
group p by new { p.SupplierID, p.SupplierStatus } into pg
select pg.Key;
The variable result is a list containing tuples of SupplierID and SupplierStatus.
If you also want to put the conditional parts in there, it gets a little more complicated. Here's how to do it:
var weights = from w in tblWeight
select w;
weights = weights.Where(w => w.SubCategory == "Sub1");
// You can add additional where clauses here.
// Now join with tblPurchases and group by SupplierID and SupplierStatus.
var result =
weights.Join(tblPurchases,
w => new { w.MemberID, w.LocationID, w.IDDesc },
p => new { p.MemberID, p.LocationID, p.IDDesc },
(w, p) => p)
.GroupBy(p => new { p.SupplierID, p.SupplierStatus },
(k, ps) => new
{
k.SupplierID,
k.SupplierStatus,
TotalQty = ps.Sum(p => p.PurchaseQty)
});

LINQ to pull back object graph

Is it possible to group by more than one group in LINQ?
For instance, I have this query (obviously incomplete)
from lxr in LOCATION_XREFs
join l in LOCATIONs on lxr.LOCATION_SKEY equals l.LOCATION_SKEY
join c in COMPANies on l.COMPANY_SKEY equals c.COMPANY_SKEY
join prlx in PeopleRoleLocationXrefs on lxr.LOCATION_XREF_SKEY equals prlx.LOCATION_XREF_SKEY
join p in PEOPLEs on prlx.PEOPLE_SKEY equals p.PEOPLE_SKEY
join pr in PeopleRoles on prlx.PeopleRoleKey equals pr.PeopleRoleKey
... and I'd like to get back a bunch of companies that have a bunch of locations that, in turn, have a bunch of people.
If you're looking to group by multiple parameters, that is possible:
from lxr in LOCATION_XREFs
join l in LOCATIONs on lxr.LOCATION_SKEY equals l.LOCATION_SKEY
join c in COMPANies on l.COMPANY_SKEY equals c.COMPANY_SKEY
join prlx in PeopleRoleLocationXrefs on lxr.LOCATION_XREF_SKEY equals prlx.LOCATION_XREF_SKEY
join p in PEOPLEs on prlx.PEOPLE_SKEY equals p.PEOPLE_SKEY
join pr in PeopleRoles on prlx.PeopleRoleKey equals pr.PeopleRoleKey
group c by new { c.COMPANY_SKEY, l.LOCATION_SKEY} into myGroup
select new
{
myGroup.Key.COMPANY_SKEY,
myGroup.Key.LOCATION_SKEY,
myGroup.Count()
}
I ultimately used the following code to achieve what I wanted. Interesting note: notice that I wanted the Roles flattened out and concatenated with commas, so I did this using a wrapper accessor that uses the Aggregate operator. Apparently the Aggregate operator is not suuported within a LINQ query, as you get "the query operator "Aggregate" is not supported" otherwise I would have done it right there inline like this Roles = new List<string>(g.Select(u => u.pr.RoleName)).Aggregate((a, b) => a + ", " + b)
public class DAOPerson
{
public string Name { get; set; }
public int PeopleSkey { get; set; }
public List<string> RolesCollection { get; set; }
public string Roles
{
get { return RolesCollection.Aggregate((a, b) => a + ", " + b); }
}
}
IQueryable<DAOLocation> gridData;
gridData = (from lxr in db.LOCATION_XREFs
join l in db.LOCATIONs on lxr.LOCATION_SKEY equals l.LOCATION_SKEY
join c in db.COMPANies on l.COMPANY_SKEY equals c.COMPANY_SKEY
where lxr.DEPARTMENT_NUMBER == Department.BINDING_AUTHORITY_KEY
&& lxr.BRANCH_NUMBER == Branch.ATLANTAKEY
orderby c.NAME, l.INTERNAL_NAME ascending
select new DAOLocation
{
CompanyName = c.NAME,
CompanySkey = c.COMPANY_SKEY,
LocationName = l.INTERNAL_NAME,
LocationSkey = l.LOCATION_SKEY,
Persons = (from prlx in db.PeopleRoleLocationXrefs
join lxr2 in db.LOCATION_XREFs on prlx.LOCATION_XREF_SKEY equals lxr.LOCATION_XREF_SKEY
join p in db.PEOPLEs on prlx.PEOPLE_SKEY equals p.PEOPLE_SKEY
join pr in db.PeopleRoles on prlx.PeopleRoleKey equals pr.PeopleRoleKey
where lxr2.LOCATION_SKEY == l.LOCATION_SKEY
group new { p, pr } by p.PEOPLE_SKEY into g
select new DAOPerson
{
Name = g.First().p.LAST_NAME,
PeopleSkey = g.First().p.PEOPLE_SKEY,
RolesCollection = new List<string>(g.Select(u => u.pr.RoleName))
}).ToList()
});

Resources