I have a SQL Query that gets Distinct rows of Vendor Contacts, which is returning the proper number of rows:
SELECT DISTINCT v.VendorID, c.ContactID,
v.VendorName,
c.FirstName, c.MiddleName, c.LastName,
FROM VendorContacts vc
INNER JOIN Contact c
ON c.ContactID = vc.ContactID
INNER JOIN Vendor v
ON v.VendorID = vc.VendorID
LEFT JOIN [ContactServices] psvc
ON psvc.ContactID = c.ContactID
AND psvc.VendorID = v.VendorID
I have a method that I want to return of custom type, based on the above query:
public List<ProviderContactInfo> GetProviderContactInfo(ProviderContactInfo searchInfo)
{
using (var db = new MyContext())
{
var providerContactInfo =
(from vc in db.VendorContacts
join ps in db.ContactServices on new { vc.ContactID, vc.VendorID } equals new { ps.ContactID, ps.VendorID } into ps_join
from ps in ps_join.DefaultIfEmpty()
join c in db.Contacts on vc.ContactID equals c.ContactID
join v in db.Vendors on vc.VendorID equals v.VendorID
orderby vc.ContactID descending
select new ProviderContactInfo()
{
VendorName = v.VendorName,
FirstName = c.FirstName,
MiddleName = c.MiddleName,
LastName = c.LastName,
Services = (from o in db.ContactServices
join cps in db.Contacts on o.ContactID equals cps.ContactID
join vps in db.Vendors on o.VendorID equals vps.VendorID
join s in db.Services on o.ServiceID equals s.ServiceID
where ps.ServiceID == o.ServiceID
&& o.ContactID == c.ContactID
&& o.VendorID == v.VendorID
select s).ToList()
}).Distinct().ToList();
return providerContactInfo;
}
}
I'm getting the error:
Additional information: The 'Distinct' operation cannot be applied to
the collection ResultType of the specified argument.
Everything works fine when I remove the Services property from the new ProviderContactInfo so I'm sure it's in the way I'm trying to populate that property (which is of type List<Service>)
I know there are a lot of questions regarding Linq with Distinct etc but I couldn't find anything on this specific problem.
Please help!
EDIT This code works:
public List<ProviderContactInfo> GetProviderContactInfo(ProviderContactInfo searchInfo)
{
using (var db = new MyContext())
{
var providerContactInfo =
(from vc in db.VendorContacts
join c in db.Contacts on vc.ContactID equals c.ContactID
join v in db.Vendors on vc.VendorID equals v.VendorID
orderby vc.ContactID descending
select new ProviderContactInfo()
{
VendorName = v.VendorName,
FirstName = c.FirstName,
MiddleName = c.MiddleName,
LastName = c.LastName,
Services = (from o in db.ContactServices
join cps in db.Contacts on o.ContactID equals cps.ContactID
join vps in db.Vendors on o.VendorID equals vps.VendorID
join s in db.Services on o.ServiceID equals s.ServiceID
where o.ContactID == c.ContactID
&& o.VendorID == v.VendorID
select s).ToList()
}).Distinct().ToList();
return providerContactInfo;
}
}
You should add one more step to the process, to avoid applying Distinct() on the objects that have a collection (Services) property, the LINQ provider does not know how to handle it.
var providerContactInfo = from vc in db.VendorContacts
join ps in db.ContactServices on new { vc.ContactID, vc.VendorID } equals new { ps.ContactID, ps.VendorID } into ps_join
from ps in ps_join.DefaultIfEmpty()
join c in db.Contacts on vc.ContactID equals c.ContactID
join v in db.Vendors on vc.VendorID equals v.VendorID
orderby vc.ContactID descending
group ps by new
{
v.VendorName,
c.FirstName,
c.MiddleName,
c.LastName,
c.ContactID,
v.VendorID
} into g
select new ProviderContactInfo()
{
VendorName = g.Key.VendorName,
FirstName = g.Key.FirstName,
MiddleName = g.Key.MiddleName,
LastName = g.Key.LastName,
Services = (from e in g
from o in db.ContactServices
join cps in db.Contacts on o.ContactID equals cps.ContactID
join vps in db.Vendors on o.VendorID equals vps.VendorID
join s in db.Services on o.ServiceID equals s.ServiceID
where e.ServiceID == o.ServiceID
&& o.ContactID == g.Key.ContactID
&& o.VendorID == g.Key.VendorID
select s).ToList()
}
Wouldn't this be much simplier:
public IQueryable<VendorContact> GetProviderContactInfo(ProviderContactInfo searchInfo)
{
using (var db = new MyContext())
{
return providerContactInfo=db.VendorContacts
.Include(vc=>vc.Contacts)
.Include(vc=>vc.Services)
.Include(vc=>vc.Vendor)
.OrderByDescending(vc=>vc.ContactID);
}
}
Related
I'm trying to write a query that contains multiple left joins in linq in a c# .netcore 2.2 application. I've tried writing the query in linq but it is not properly retrieving all the rows. Query I'm trying to convert is as follows.
select ISNULL(b.Id, '00000000-0000-0000-0000-000000000000') as 'Bat Id', p.Id as 'ProductId', p.RP, u.UnitName as 'UnitName', ISNULL(b.QTY,0) as 'BusQty', p.[Name] as 'Product Name'
from Products p left join Bat b
ON p.Id = b.ProductId
left join Units u on p.UOId = u.Id;
linq I have so far
var allProducts = (from p in _db.Products
join s in _db.Bat on p.Id equals s.ProductId into ps
from s in ps.DefaultIfEmpty()
join u in _db.Units on p.UOId equals u.Id
select new
{
BatId = s.Id == null ? Guid.NewGuid() : s.Id,
RP = p.RP,
BusQty = s.QTY == null ? 0 : s.QTY,
ProductName = p.Name,
UnitName = u.UnitName,
ProductId = p.Id,
}).ToList();
You are missing DefaultIfEmpty() on Units, thereby turning it into an inner join
var allProducts = (
from p in _db.Products
join s in _db.Bat on p.Id equals s.ProductId into ps
from s in ps.DefaultIfEmpty()
join u in _db.Units on p.UOId equals u.Id into us
from u in us.DefaultIfEmpty()
select new
{
BatId = s.Id ?? Guid.NewGuid(),
RP = p.RP,
BusQty = s.QTY ?? 0,
ProductName = p.Name,
UnitName = u.UnitName,
ProductId = p.Id,
}).ToList();
Whith s_records, q_records, d_records, i_records all of type IEnumerable<MyRecord>, querytwo works just as expected. But what if I want to join multiple IEnumerable on the same equality of the same fields?
var querytwo = from a in s_records
join b in q_records
on a.date equals b.date
select new { s_line = a.line, q_line = b.line };
Console.WriteLine(querytwo.Count());
This query doesn't work I am trying to do the same as in querytwo, but join on multiple IEnumerable<MyRecord>:
var query = from a in s_records
join b in q_records
join c in d_records
join d in i_records
on a.date equals b.date equals c.date equals d.date
select new { s_line = a.line, q_line = b.line, d_line = c.line, i_line = d.line };
Your syntax is to off to some extent. it should be:
var querytwo = from a in s_records
join b in q_records on a.date equals b.date
join c in d_records on b.date equals c.date
join d in i_records on c.date equals d.date
select new {
s_line = a.line,
q_line = b.line,
d_line = c.line,
i_line = d.line
};
Here I want to join the out put of the first query(one column) to the result of the 2nd query to get a one result set. How can I merge them.(CONCAT doesn't work as required. eg: var query2 = query.concat(query1);)
var query = (from PP in _db.paymentPlans
join APP in _db.Applications on PP.applicationID equals APP.ApplicationId
join C in _db.Courses on APP.courseID equals C.courseID
where PP.active == true && APP.agentID == agentID
orderby C.courseID ascending
group new {C,PP} by new {C.courseID} into totalRecievable
select new PdPpAppCourseModel
{
courseID = totalRecievable.Key.courseID,
totalAmount = totalRecievable.Sum(x => x.PP.totalAmount)
}).ToList();
var query1=(from PD in _db.paymentDetails
join PP in _db.paymentPlans on PD.paymentPlanID equals PP.paymentPlanID
join APP in _db.Applications on PP.applicationID equals APP.ApplicationId
join C in _db.Courses on APP.courseID equals C.courseID
where PP.active == true && APP.agentID == agentID
orderby C.courseID ascending
group new { C,PD } by new { C.courseID, C.cricosCode, C.courseName } into paymentsCourseWise
select new PdPpAppCourseModel
{
courseID = paymentsCourseWise.Key.courseID,
cricosCode = paymentsCourseWise.Key.cricosCode,
courseName = paymentsCourseWise.Key.courseName,
paidAmount = paymentsCourseWise.Sum(x => x.PD.paidAmount)
}).ToList();
You could join query1 and query like this
var result = (from q1 in query1
join q in query on q1.courseID = q.courseID
select new PdPpAppCourseModel
{
courseID = q1.Key.courseID,
cricosCode = q1.Key.cricosCode,
courseName = q1.Key.courseName,
paidAmount = q1.Sum(x => x.PD.paidAmount),
totalAmount = q.totalAmount
}).ToList();
I'm working with the following linq query:
var docList = from c in container.DocumentDeliveryPreferences
join o in container.Documents on c.DocumentId equals o.DocumentId
select new { o.Name, o.DocumentType, c.CustomerId };
How can I modify this to select only Documents where c.CustomerId equals X(some paramenter)?
You could try something the following:
var docList = from c in container.DocumentDeliveryPreferences
join o in container.Documents
on c.DocumentId equals o.DocumentId
where c.CustomerId == X
select new { o.Name, o.DocumentType, c.CustomerId };
where X is your parameter.
I have written the below given query in SQL server 2008:
(SELECT p.postid,
p.title,
p.disabled,
l.locationname
FROM posts p
INNER JOIN categories c
ON p.categoryid = c.categoryid
INNER JOIN users u
ON p.userid = u.userid
INNER JOIN tags t
ON p.tagid = t.tagid
INNER JOIN locations l
ON p.locationid = l.locationid
LEFT JOIN postimages pm
ON p.postid = pm.postid
WHERE p.categoryid = 1
GROUP BY p.postid,
p.title,
p.disabled,
l.locationname)
ORDER BY p.postid DESC
I want to write the above query in LINQ.
I tried a little and able to write the query below:
var objPosts = (from p in _dbcontext.Posts
join us in _dbcontext.Users on p.UserId equals us.UserId
join tag in _dbcontext.Tags on p.TagId equals tag.TagId
join cat in _dbcontext.Categories on p.CategoryId equals cat.CategoryId
join loc in _dbcontext.Locations on p.LocationId equals loc.LocationId
join img in _dbcontext.PostImages on p.PostId equals img.PostId into gj
from postimg in gj.DefaultIfEmpty()
where p.Disabled == false && p.CategoryId == userPost.CategoryId || p.UserId == userPost.UserId || p.TagId == userPost.TagId || p.LocationId == userPost.LocationId
orderby p.PostId descending
select new
{
PostId = p.PostId,
PostTitle = p.Title,
//ImageInfo = postimg.ImagePath,
//ThumbNailInfo = p.ThubNailInfo,
PostShortDescription = p.ShortDescription,
UserId = us.UserId,
UserName = us.Name,
TagId = tag.TagId,
TagTitle = tag.Title,
CategoryId = cat.CategoryId,
CategoryName = cat.CategoryName,
LocationId = loc.LocationId,
LocationName = loc.LocationName
});
I am unable to apply the group by logic in LINQ. Can anyone please convert my SQL to LINQ. Thanks
group new { p, l } by new
{
p.postid,
p.title,
p.disabled,
l.locationname
} into g
orderby g.Key.PostId descending
select new
{
g.key.postid,
g.key.title,
g.key.disabled,
g.key.locationname
}
The missing part in your query is that you are not selecting anything...
You got the joins ok, left outer join ok, predicates (where), ordering, but no projection, and no group by.
Below should get you started:
group p by p.PostId into pg
select new {Post=p, Location=loc};
This would return return a collection of new objects whose properties Post and Location.