Whats wrong with this LINQ query (joins) - linq

Vendors Vendorsid PointTo
123 456
456 412
789 853
Items StandardItemNumber VendorSID SerialNumber
1234 123 A1234
4567 123 A4567
8523 456 A8523
1234 456 A1234
From the procedure, I get 123 and point to as 456. I want to check if items from 123 are already there under vendor 456. So dupes should give me item 1234 since its present with vendor 456 with same Serial number.
But dupes is not getting executed at all. It hangs at that statement.
var vendors = db.hp_GetEligibleVendors();
var items = from i in db.Items
where i.VendorID.Equals(vendors.VendorID)
select i;
foreach(var vendor in vendors)
{
var items = from i in db.Items
where i.VendorSID.Equals(vendor.VendorSID)
select i;
var dupes = from oi in items join di in db.Items
on new
{
oi.ItemNumber,
oi.SerialNumber
}
equals new
{
ItemNumber = di.ItemNumber,
SerialNumber = di.SerialNumber
}
where di.VendorSID.Equals(vendor.PointToVendorSID)
select oi;
}
In the above query, it takes forever to get dupes. What is wrong with this query?

I was able to resolve the issue. I had to add ItemNumber = oi.ItemNumber,SerialNumber = oi.SerialNumber. That solved the proble. Thanks to all who replied.

Related

LinQ Query for selecting multiple data in single row

I have following two tables with data.
Table: Pond
Pond_ID Pond_Owner
01 Nasir
02 John
Table: Fish
Pond_ID Fish_Name
01 Koi
01 Carp
02 Cat Fish
02 Gold Fish
02 Comet
02 Magur
It is noted that Pond_ID field is the primary key in Pond Table and Foreign key in Fish Table. Now I would like to write a LinQ Query to the result like bellow.
Expected Result
Pond_ID Pond_Owner Fish_Name
01 Nasir Koi, Carp
02 John Cat Fish, Gold Fish, Comet, Magur
So anyone can help me to write this linQ query. Thanks in advance.
You have to group them on PondID and OwnerName :
var result = from p in db.pond
join f in db.Fish on p.Pond_Id equals f.Pond_Id
group f by new
{
f.Pond_Id,
f.Owner_name
} into g
select new
{
Owner = g.Key.Owner_Name,
Fishes = String.Join(",",g.Select(x=>x.Fish_Name))
}
then iterate on result set:
foreach(var item in result)
{
Console.WrtieLine(String.Format("Owner Name : {0} , Fishes : {1}",item.Owner,item.Fishes))
}
UPDATE:
var result = from p in db.pond
join f in db.Fish on p.PondID equals f.PondID
group f by new { f.PondID,p.OwnerName } into g
select new { Owner = g.Key.OwnerName, Fishes = String.Join(",",g.Select(x=>x.FishName))};
foreach(var item in result)
{
Console.WriteLine(String.Format("Owner : {0} and Fishses : {1}",item.Owner,item.Fishes));
}
See this WORKING FIDDLE EXAMPLE for more.
You can perform join operations on LINQ like:
var result = (from p in dbContext.Pond
join f in dbContext.Fish
on p.Pond_ID == f.Pond_ID
select new
{
Pond_ID = p.Pond_ID,
Pond_Owner = p.Pond_Owner,
Fish_Name = f.Fish_Name
}).ToList();
Above query will perform full Join. In case you want to perform left outer join, you can do the same operation using DefaultIfEmpty() as:
var result = (from p in dbContext.Pond
join f in dbContext.Fish
on p.Pond_ID == f.Pond_ID into group1
from g1 in group1.DefaultIfEmpty()
select new
{
Pond_ID = p.Pond_ID,
Pond_Owner = p.Pond_Owner,
Fish_Name = g1.Fish_Name
}).ToList();

LINQ: Drill down to value in query results

I am using LINQ for the first time and have the following query:
var query = from c in context.Call
join d in context.CallData on c.CallID = d.CallID
where c.CallID == 123
select new {
c.CallID,
c.CallResult,
d.FieldID,
d.FieldValue
};
This returns data similar to the following
c.CallID c.CallResult d.FieldID d.FieldValue
123 Sale 345 John
123 Sale 346 Doe
123 Sale 347 888-222-3333
How can drill down to the row containing d.FieldID = 346 to get the value of d.FieldValue (346 being the LastName field)? I would like to use this value as the new value of a local variable:
// I know this doesn't work, just showing what I would like to accomplish
string LastName = query.Select(a => a.FieldID = 346).FieldValue;
Conversely, how can I change the value of c.CallResult once I have these results? Since it is a join, can I simply change one row of data or do I have to do a separate query?
For the first question you can move on from your query variable:
var fieldValue = query.Where(x => x.FieldID == 346).Single().FieldValue;
As for your second question: you must apply a change to the original entity object:
var call = context.Find(123);
// or context.Calls.Single(c => c.CallId == 123) if this is not DbContext.
call.CallResult = newValue;
context.SaveChanges();
Do you mean:
string LastName = query
.Where(a => a.FieldID = 346)
.Select(a => a.FieldValue)
.FirstOrDefault();

LINQ get first value in given list

I have a list(mainlist) with the following
PsID Nominprsn
---- ---------
1 James
2 Troy
2 William
3 Mike
4 Jason
4 Hendry
I need to get the first name from a given PsID
so the result would be as such
PsID Nominprsn
---- ---------
1 James
2 Troy
3 Mike
4 Jason
I tried the following but was not successful as I didn't know how to get the first PsID:
var proglis = (from ts in mainlist
group ts by new { ts.PsID, Nominprsn} into grp
select new {grp.Key.PsID grp.Key.Nominprsn}).ToList();
To select the first item from each group use this query:
var query = mainlist.GroupBy(o => o.PsID)
.Select(g => new { PsID = g.Key, g.First().Nominprsn })
.ToList();
This will return the same results you've shown in your question. The result will be an IEnumerable of anonymous types with properties named PsID and Nominprsn.
Here is how you should do it:
var proglis = (from ts in mainlist
group ts by ts.PsID into grp
select new
{
Id = grp.Key,
Name = grp.First().Nominprsn
}).ToList();
Or maybe try Distinct or DistinctBy(o => o.Key.PsID)

How to Update previous row column based on the current row column data using LinQ

var customer= from cust in customerData
select new Customer
{
CustomerID = cust["id"],
Name = cust["Name"],
LastVisit = cust["visit"],
PurchashedAmount = cust["amount"],
Tagged = cust["tagged"]
Code = cust["code"]
}
The rows looks like this
Name LastVisit PurchasedAmount Tagged Code CustomerID
------ --------- -------------- ------ ----- -----
Joshua 07-Jan-09 Yes chiJan01 A001
Joshua 10000
The 2nd row belongs to first row just that the other columns are empty.How can i merge the PurchasedAmount into the first row using LinQ?
This is probably a more general solution than you need - it will work even if the other values are scattered across rows. The main condition is that the Name column should identify rows that belong together.
customer = from c in customer
group c by c.Name
into g
select new Customer
{
Name = g.Key,
LastVisit = g.Select(te => te.LastVisit).
Where(lv => lv.HasValue).FirstOrDefault(),
PurchaseAmount = g.Select(te => te.PurchaseAmount).
Where(pa => pa.HasValue).FirstOrDefault(),
Tagged = g.Select(te => te.Tagged).
Where(ta => ta.HasValue).FirstOrDefault(),
Code = g.Select(te => te.Code).
Where(co => !string.IsNullOrEmpty(co)).FirstOrDefault(),
CustomerID = g.Select(te => te.CustomerID).
Where(cid => !string.IsNullOrEmpty(cid)).FirstOrDefault()
};
This will return a new IEnumerable with the items grouped by Name and the non-null values selected (same effect as moving PurchasedAmount to the first row and deleting the second in your case).
Note that the code is based on the assumption that LastVisit, PurchaseAmount and Tagged are nullable types (DateTime?, int? and bool?). Thus the usage of HasValue. If, however, they are strings in your case, you have to use !string.IsNullOrEmpty() instead (as for Code and CustomerID).

Is a dynamic pivot using LINQ possible?

I have a T-SQL 2005 query which returns:
pid propertyid displayname value
----------- ----------- --------------- ---------------
14270790 74 Low Price 1.3614
14270790 75 High Price 0
14270791 74 Low Price 1.3525
14270791 75 High Price 0
14270792 74 Low Price 1.353
14270792 75 High Price 0
14270793 74 Low Price 1.3625
14270793 75 High Price 0
14270794 74 Low Price 1.3524
14270794 75 High Price 0
What I would like to do is essentially pivot on the displayname field, hopefully producing:
pid Low Price High Price
14270790 1.3614 0
14270791 1.3525 0
14270792 1.353 0
14270793 1.3625 0
14270794 1.3524 0
(Not sure how the propertyid field would be output, so I left it out (was hoping it would simply sit alongside the Low Price and High Price fields, to indicate their IDs, but I don't think that will work.)
The problem is that the content of the original displayname field is dynamic - it is produced from a join with a PropertyName' table, so the number of pivoted columns is variable. It could therefore containHigh Price,Low Price,OpenandClose`, depending on what the join with that table returns.
It is, of course, relatively easy (regardless of the trouble I'm having writing the initial query!) to produce this pivot in a fixed query or stored proc. However, is it possible to get LINQ to generate a SQL query which would name each column to be produced rather than having to write a dynamic (probably in a stored proc) query which lists out the column names?
Thanks,
Matt.
I'll give you a sample with a different data (that I needed). You can adapt that to your need. Note only two linq queries are used, most of the other fluff is to convert a list into a datatable.
var data = new[] {
new{Student=1, Subject="English", Marks=40},
new{Student=1, Subject="Maths", Marks=50},
new{Student=1, Subject="Science", Marks=60},
new{Student=1, Subject="Physics", Marks=70},
new{Student=1, Subject="Chemistry", Marks=80},
new{Student=1, Subject="Biology", Marks=90},
new{Student=2, Subject="English", Marks=4},
new{Student=2, Subject="Maths", Marks=5},
new{Student=2, Subject="Science", Marks=6},
new{Student=2, Subject="Physics", Marks=7},
new{Student=2, Subject="Chemistry", Marks=8},
new{Student=2, Subject="Biology", Marks=9}
};
/*Here the pivot column is the subject and the static column is student
group the data against the static column(s)*/
var groups = from d in data
group d by d.Student into grp
select new
{
StudentId = grp.Key,
Marks = grp.Select(d2 => new { d2.Subject, d2.Marks }).ToArray()
};
/*get all possible subjects into a separate group*/
var subjects = (from d in data
select d.Subject).Distinct();
DataTable dt = new DataTable();
/*for static cols*/
dt.Columns.Add("STUDENT_ID");
/*for dynamic cols*/
foreach (var subject in subjects)
{
dt.Columns.Add(subject.ToString());
}
/*pivot the data into a new datatable*/
foreach (var g in groups)
{
DataRow dr = dt.NewRow();
dr["STUDENT_ID"] = g.StudentId;
foreach (var mark in g.Marks)
{
dr[mark.Subject] = mark.Marks;
}
dt.Rows.Add(dr);
}
This is the closest I could get, but it's not LINQ...
create table #t
(
pointid [int],
doublevalue [float],
title [nvarchar](50)
)
insert into #t
select
distinct top 100
v.pointid, v.doublevalue, p.title
from [property] p
inner join pointvalue v on p.propertyid = v.propertyid
inner join point pt on v.pointid = pt.pointid
where v.pointid in (select top 5 p.pointid from point p where p.instanceid = 36132)
declare #fields nvarchar(250)
set #fields = (select STUFF((SELECT N',[' + title + ']' FROM [property] FOR XML PATH('')), 1, 1, N''))
--select #fields
declare #sql nvarchar(500)
set #sql = 'select * from #t
pivot
(
sum(doublevalue)
for [title] in ('+#fields+')
) as alias'
--select #sql
exec (#sql)
drop table #t
The kicker is that I'm simply asking for every entry in the Property table, meaning there's a lot of columns, in the resulting pivot, which have NULL values.
the code I think is like this:
var list = from table in Property
group table by table.pid into g
select new
{
pid = g.key,
LowPrice = g.Where(w => w.pid== g.key && w.priceType == "low").Select(s => s.value).FirstorDefault(),
HighPrice = g.Where(w => w.pid== g.key && w.priceType == "high").Select(s => s.value).FirstorDefault(),
};
Hope it can help you and have a nice day.

Resources