Linq to get complete row based on duplicate values in column - c#

I am looking for a LINQ to use with my datatable and display all the duplicate rows based on certain columns in windows form datagrid view.
The LINQ should give a result similar to the plain old below give SQL.
SELECT *
FROM Table1 t
JOIN ( SELECT Taskid, Studentid, DateChangeid
FROM Table1
GROUP BY Taskid, studentid, datechangeid
HAVING COUNT(*) > 1) temp
ON t.taskid = temp.taskid AND t.studentid= temp.studentid AND t.datechangeid= temp.datechangeid

This should do what you want:
var result =
t.GroupBy(g => new {TaskId = Taskid, StudentId = studentid, DatechangeId = datechangeid})
.Where(g => g.Count > 1)
.ToList();
Now you're joining Table1 on Table1 which isn't needed, just do the filtering on Table1 only.
Now the result will be of type List<IGrouping<'a,Table1>> though because of the anonymous keyselector, you can also define TaskId , StudentId and DateChangeID in a class to get rid of that. For example:
public class Table1GroupKey
{
public int TaskId {get; set;}
public int StudentId {get; set;}
public int DateChangeId {get; set;}
}
Then you can use:
GroupBy(g => new Table1GroupKey { ... })
And your result will be List<IGrouping<Table1GroupKey,Table1>>.

I managed it by writing two linq as given below.
var RepeatedValues = from d in DataTableitems.AsEnumerable()
group d by d.Field<string>("MobileNo") into itemGroup
where itemGroup.Count() > 1
select new { name = itemGroup.Key };
var RepeatedInRows= from d in DataTableitems.AsEnumerable()
join c in RepeatedValues.AsEnumerable() on d.Field<string>
("MobileNo") equals c.name
select d;

Related

Query- LINQ, 2 tables, Union

These are my two tables:
publicParking(publicParkingID, address, latitude, longtitude, status,
PricePerHour, maxSpaces, occupiedSpaces, freeSpaces, isOrdered)
and
parkingLot(parkingLotID, address, latitude, longtitude, status,
PricePerHour, maxSpaces, occupiedSpaces, freeSpaces, isOrdered)
All of the columns are the same except the ID.
I need to write query in LINQ that will return a table ordered by price with all the available parkings (publicParking / parkingLot) - with status==true.
The table should look like this:
ID address latitude longitude status
Should I do a union, or should I change the table so the first column will call just ID? (instead of publicParkingID and parkingLotID)
I've tried this code but it does not work
var union =
(from lot in parkingLots
where lot.status == true
select lot).Union( from pub in publicParkings
where pub.status==true
select pub);
It give this error :
I am working with LINQPad5 and with code editor of tutorialsteacher. Are there are other options?
To use Union both result sequences must contain the same types. In your example the outer query contains parkingLot and the inner publicParking.
It could be solved using anonymous types:
var union =
(from lot in parkingLots
where lot.status == true
orderby lot.PricePerHour // don't forget ordering
select new {
ID = lot.parkingLotID,
lot.address, lot.latitude, lot.longitude, lot.status})
.Union(from pub in publicParkings
where pub.status==true
orderby pub.PricePerHour // don't forget ordering
select new {
ID = pub.publicParkingID,
pub.address, pub.latitude, pub.longitude, pub.status});
But maybe better for further data handling would be a custom class:
public class ParkingData
{
public int ID {get; set;}
public string Address {get; set;}
public double Latitude {get; set;}
public string Longitude {get; set;}
public bool Status {get; set;}
}
and query like that:
var union =
(from lot in parkingLots
where lot.status == true
orderby lot.PricePerHour // don't forget ordering
select new ParkingData {
ID = lot.parkingLotID,
Address = lot.address,
Latitude = lot.latitude,
Longitude = lot.longitude,
Status = lot.status})
.Union(from pub in publicParkings
where pub.status==true
orderby pub.PricePerHour // don't forget ordering
select new {
select new ParkingData {
ID = pub.publicParkingID,
Address = pub.address,
Latitude = pub.latitude,
Longitude = pub.longitude,
Status = pub.status});

left non equi join linq

I have a list of objects in table tblB which is retrieved from db in following format.
public class playdata
{
public string consumerid { get; set; }
public string play_time { get; set; }
public string genre{ get; set; }
.
.
.
public int mycounter{ get; set; }
}
I have a table tblA which has a column colA which has int from 0 to 1000.
I wish to create a linq query similar to sql as below..
Select x.i as numindex, y.consumerid,y.play_time,y.genre
From
(Select colA as i from tblA) x
left join
(
Select consumerid, play_time,genre,mycounter from tblB
)y on y.mycounter > x.i
I tried the following unsuccessfully..
I came to find that Enumerable.Range(0, 1001) generated a numeric series so no need to get that table data..
List<playdata> plays = .....
var q= (from s in Enumerable.Range(0, 1001)
join p in plays on s < p.mycounter into t
from rt in t.DefaultIfEmpty() select new{
numindex=s,
consumerid=p.consumerid,
play_time =p.play_time,
genre=p.genre
}).ToList();
I see two errors in second line..
p is not in scope of left side of equals .. I have also tried..p.mycounter>s with same result.
The other error is in into where it shows.. expected contextual keyword equals
The errors go away if I change the second line to..
join p in plays on s equals p.mycounter into t
All help is sincerely appreciated.
Thanks
You have to use the alternative way of representing left outer join in LINQ:
var q =
(from i in Enumerable.Range(0, 1001)
from p in plays.Where(x => x.mycounter > i).DefaultIfEmpty()
select new
{
numindex = i,
consumerid = p?.consumerid,
play_time = p?.play_time,
genre = p?.genre
}).ToList();
Note that in LINQ to Objects you have to account for right side of the left outer join returning null when there is no matching element, otherwise you'll get NullReferenceException.

Dapper returning a sub set of specific columns directly into DTO

Can Dapper return data directly into a DTO/POCO that only has a subset of fields - ie can I it use classes that do not contain all the columns in the db tables?
Eg if I have the following query (excuse my sql - not my strong point):
select c.Name as "Customer", o.Number as "OrderNo", ol.Number as "Line", p.Description as "Product", ol.Qty
from order o
join customer c on c.Id = o.CustomerId
join orderLine ol on ol.OrderID = o.Id
join product p on p.Id = ol.ProductId
where o.date >= 1/9/2013 and o.date <= 30/9/2013
How can I use Dapper to read this into an array/IEnumerable of the following class:
class CustOrders{
string Customer {get;set;}
integer Order {get;set;}
string Line {get;set;}
string Product {get;set;}
integer Qty {get; set;}
}
Thanks
Tim
you can do as below
var sql = #"select c.Name as [Customer], o.Number as [Order], ol.Number as [Line], p.Description as [Product], ol.Qty ...";
var result = connection.Query<CustOrders>(query);

Multiple joins to the same type in PetaPoco

Question:
I'm trying to use PetaPoco to join more than four tables to populate an object of type A with five members of type B (very similiar to this question: https://stackoverflow.com/a/11275334/296296). From what I've read it would be possible to use this syntax:
var result = db.Query<Investment>(new System.Type[] { typeof(Investment), typeof(Person), typeof(Person), typeof(Person), typeof(Person), typeof(Person) }, null, sql, null).FirstOrDefault();
Where the sql is:
SELECT Investment.*, p1.*, p2.*, p3.*, p4.*, p5.* FROM Investment
INNER JOIN People p1 ON Investment.OwnerID = p1.Id
INNER JOIN People p2 ON Investment.ITOwnerID = p2.Id
INNER JOIN People p3 ON Investment.InformationOwnerId = p3.Id
INNER JOIN People p4 ON Investment.MaintenanceLeaderId = p4.Id
INNER JOIN People p5 ON Investment.MaintenanceLeaderITId = p5.Id
WHERE (Investment.Id = #0)
But it just gives me the following error:
Can't auto join Person as Investment has more than one property of type Person
Anyone who had the same problem or could help in any way?
Background:
I have the following (simplified) database tables:
Investment
--------------
Id
Name
OwnerId
ITOwnerId
InformationOwnerId
MaintenanceLeaderId
MaintenanceLeaderITId
People
--------------
Id
Name
The classes I would like to map these database tables to are:
Public class Investment {
public int Id
public string Name
public Person Owner
public Person ITOwner
public Person InformationOwner
public Person MaintenanceLeader
public Person MaintenanceLeaderIT
}
Public class Person {
public int Id
public string Name
}
In order to do so, I need to join the People table for every Person-type in the Investment class and map them to the corresponding property as instances of the type Person.
The only way you could possibly do this is create your own callback (instead of letting it fall back to the self discovering callback thats currently being invoked) where you wire up each Person object on the Investment object.
Take a look at http://www.toptensoftware.com/Articles/115/PetaPoco-Mapping-One-to-Many-and-Many-to-One-Relationships
why can't you do this :
/////SQL CODE for testing the selects
DECLARE #People TABLE (Id INT, Name VARCHAR(50))
INSERT INTO #People (Id,Name)
SELECT 1,' John Smith' UNION ALL
SELECT 2,'Albert Lee' UNION ALL
SELECT 3,'Christina Wetherbe' UNION ALL
SELECT 4,'Alice Cany' UNION ALL
SELECT 5,'Jim Blabery' UNION ALL
SELECT 6,'Octaviose Mayflower' UNION ALL
SELECT 7,'Sandra Lee M' UNION ALL
SELECT 8,'Some test user' UNION ALL
SELECT 9,'Some test user 2' UNION ALL
SELECT 10,'Some test user 3' UNION ALL
SELECT 11,'Some test user 4'
DECLARE #Investment TABLE (
Id INT,
Name VARCHAR(50),
OwnerId INT,
ITOwnerId INT,
InformationOwnerId INT,
MaintenanceLeaderId INT,
MaintenanceLeaderITId INT
)
INSERT INTO #Investment(Id,Name,OwnerId,ITOwnerId,InformationOwnerId,MaintenanceLeaderId,MaintenanceLeaderITId)
SELECT 1,'INVESTMENT 1',1,2,1,3,4 UNION ALL
SELECT 2,'INVESTMENT 2',1,3,2,3,2 UNION ALL
SELECT 3,'INVESTMENT 3',3,1,3,3,4 UNION ALL
SELECT 4,'INVESTMENT 4',5,4,4,2,3 UNION ALL
SELECT 5,'INVESTMENT 5',6,5,5,7,6 UNION ALL
SELECT 6,'INVESTMENT 6',8,6,6,7,8 UNION ALL
SELECT 7,'INVESTMENT 7',9,8,7,4,5 UNION ALL
SELECT 8,'INVESTMENT 8',11,8,8,6,11 UNION ALL
SELECT 9,'INVESTMENT 9',10,9,9,10,9
--SELECT * FROM #People
--SELECT * FROM #Investment
-- THIS IS YOUR SELECT STATEMENT to be uses in PetaPoco call
SELECT unpv.Id,unpv.Name, unpv.INVTYPE,unpv.PersonId,p.Name FROM #Investment
UNPIVOT(PersonId for INVTYPE in (OwnerId,ITOwnerId,InformationOwnerId,MaintenanceLeaderId,MaintenanceLeaderITId))unpv
join #People p on unpv.PersonId = p.Id
order by INVTYPE, PersonId
Then C# code as
1 - Extend your Investment POCO to have 2 more columns, INVTYPE and PersonId. Just create new object in the same name-space. Like so:
public partial class Investment
{
[ResultColumn]
public string INVTYPE { set; get; }
[ResultColumn]
public int PersonId { set; get; }
}
2 - create viewclass InvestmentView (you can use your Investment class for that, just rename it)
var myInvestmentView = new InvestmentView
{
Id = result.Id,
Name = result.Name,
Owner = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("OwnerId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("OwnerId")).PersonName},
ITOwner = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("ITOwnerId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("ITOwnerId")).PersonName},
InformationOwner = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("InformationOwnerId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("InformationOwnerId")).PersonName},
MaintenanceLeader = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("MaintenanceLeaderId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("MaintenanceLeaderId")).PersonName},
MaintenanceLeaderIT = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("MaintenanceLeaderITId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("MaintenanceLeaderITId")).PersonName}
}
3 - populate the class with data from the list returned
using (var data = new Database(Config.MainDbConnectionName))
{
var result = data.Fetch<Investment,People>(
Sql.Builder
.Append("SELECT unpv.Id,unpv.Name, unpv.INVTYPE,unpv.PersonId,p.name as PersonName FROM Investment")
.Append(" UNPIVOT(PersonId for INVTYPE in (OwnerId,ITOwnerId,InformationOwnerId,MaintenanceLeaderId,MaintenanceLeaderITId)) unpv")
.Append(" JOIN People p on unpv.PersonId = p.Id")
.Append(" WHERE (Investment.Id = #0)",InvId)
.Append(" ORDER BY INVTYPE, PersonId")
);
}
this way the only class that will need the special treatment will be Investment class as you would need to process the data backwards from InvestmentView into flat structure of POCO.

SQL Linq Question

I have the following working TSQL query in ms SQL 2008
SELECT
Date,
COUNT(click) AS clicks,
COUNT(sale) AS sales,
count(lead) as leads
FROM
(
SELECT ClickDate as date ,ID AS click ,CAST(NULL AS int) AS sale , CAST(null as int) as lead
FROM clicks
UNION ALL
SELECT Date,null, ID ,NULL
FROM sales
UNION ALL
SELECT Date,null, NULL ,ID
FROM leads
) t
GROUP BY Date
How would i convert this to LINQ to SQL?
I wrote this LINQ but it doesn't work.
public class mydata
{
public DateTime date { get; set; }
public int? click { get; set; }
public int? sale { get; set; }
public int? lead { get; set; }
}
var clicks = from c in Clicks
select new mydata
{
date = c.ClickDate, click = c.ID, sale = null, lead = null
};
var sales = from s in Sales
select new mydata
{
date = s.Date, click = null, sale = s.ID, lead = null
};
var leads = from l in Leads
select new mydata
{
date = l.Date, click = null, sale = null, lead = l.ID
};
var v = clicks.Concat(sales).Concat(leads);
var res = from x in v
group x by x.date into xg
select new
{
date = xg.Key, clicks = xg.Count(z => z.click != null)
};
}
How do i correct this LINQ query?
Update:
i Modified the LINQ query based on David B recommendation.
i'm still getting the following error:
"All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists."
David's correct about the first two issues. For your final problem (3), Count() does not work like it does in SQL. It expects a predicate that returns a bool. Your using it with ints (i.e. z.click, z.sales, etc.)
The problem is that the anonymous types in the projections are not identical... ID is int in one and Nullable<int> in another.
Instead of using an anonymous type in your projections, use this:
public class ConcatTarget
{
public DateTime TheDate {get;set;}
public int? ID {get;set;}
public string sale {get;set;}
public string lead {get;set;}
}
Even though no instances are actually constructed, LinqToSql uses the class's shape to translate the query.
As for Count, perhaps you meant .Count(x => x.Prop != null) ?
Ok, apparently you've hit upon a buggy translation behavior as described here.
What's happening is the sql translator sees the null assignments, and throws them away. This causes an incorrect number of sql columns to be selected between the sets.
Here's a possible workaround:
int? myNull = null;
var clicks =
from c in Clicks
select new mydata
{
date = c.ClickDate,
click = c.ID,
sale = c.ID + myNull,
lead = myNull + c.ID //note - expressions must be unique
};
The basic idea is to create unique expressions the query translator can't throw away. This is harder than it sounds (above is my ninth attempt).
Here's the other two tables:
var sales = from s in Sales
select new mydata
{
date = s.Date,
click = s.ID + myNull,
sale = s.ID,
lead = myNull + s.ID
};
var leads = from l in Leads
select new mydata
{
date = l.Date,
click = l.ID + myNull,
sale = myNull + l.ID,
lead = l.ID
};
If you had more than 2 columns-to-be-nulled, you could resort to subtraction, division, multiplication, etc.

Categories