I am new to LINQ and have been trying to write a linq query that would be equivalent to the following SQL statement:
SELECT linking."RfidNumber",
linking."VehicleID",
acs."Date",
Min(acs."acs_datetime" ) as INTIME,
Max(acsout."acs_datetime" )
FROM dbo."acs_transaction_new" acs
INNER JOIN dbo."acs_transaction_new" acsout
ON acs."Date" = acsout."Date" AND acs."acs_operations" = 'in' AND
acsout."acs_operations" = 'out'
INNER JOIN dbo."PassLinkings" linking ON acs."acs_rfid_no" = linking."RfidNumber" AND
acs."acs_vehicle_id" = linking."VehicleID"
WHERE acsout."acs_operations" = 'out' AND acs."acs_operations" = 'in'
GROUP BY linking."RfidNumber", linking."VehicleID", acs."Date";
Basically I want MIN acs."acs_datetime"
where acs."acs_operations"='in'
and similarly MAX acs."acs_datetime"
where acs."acs_operations"='out'
for each date in the table for unique combination of RfidNumber
and VehicleID
I am lost at Linq:
var query1 = (from acs in db.acs_transaction
join acsout in db.acs_transaction on acs.acs_datetime equals acsout.acs_datetime
join linking in db.PassLinkings on new { rfid = acs.acs_rfid_no, vehicleid = acs.acs_vehicle_id } equals new { rfid = linking.RfidNumber, vehicleid = (linking.VehicleID == null ? -1 : (int)linking.VehicleID) }
where acs.acs_operations == "in" && acsout.acs_operations == "out"
select new { acs.acs_rfid_no,
acs.VehicleID ,
acs."Date",
Min(acs."acs_datetime" ),// something like that
Max(acs."acs_datetime" )
}).ToList(); ;
From the Query that you have posted following is my understanding of your models:
public class Acs_Transaction_New_class
{
public DateTime Date {get; set;}
public string acs_operations {get; set;}
public int acs_rfid_no {get; set;}
public int acs_vehicle_id {get; set;}
public DateTime acs_datetime {get; set;}
}
public class PassLinking_Class
{
public int RfidNumber { get; set; }
public int VehicleID { get; set; }
}
// Data Placeholders to compile linq query
var result = Acs_Transaction_New
.Join(Acs_Transaction_New, acs => acs.Date, acsout => acsout.Date, (acs, acsout) => new { acs, acsout })
.Where(x => x.acs.acs_operations == "in" && x.acsout.acs_operations == "out")
.Join(PassLinkings, x => new { rfid = x.acs.acs_rfid_no, vehicleid = x.acs.acs_vehicle_id }, linking => new { rfid = linking.RfidNumber, vehicleid = linking.VehicleID}, (x, linking) => new { x.acs, x.acsout,linking })
.GroupBy(x => new { x.linking.RfidNumber, x.linking.VehicleID, x.acs.Date })
.Select(x => new
{
x.Key.RfidNumber,
x.Key.VehicleID,
x.Key.Date,
acs_min_datetime = x.Min(y => y.acs.acs_datetime),
acs_max_datetime = x.Max(y => y.acsout.acs_datetime)
});
acs_operations == "in" / "out"
as Where condition, instead of Join, ideally we don't need comparison with "in" and "out" twice var result = from acs in Acs_Transaction_New
join acsout in Acs_Transaction_New on acs.Date equals acsout.Date
where acs.acs_operations == "in" && acsout.acs_operations == "out"
join link in PassLinkings on new { rfid = acs.acs_rfid_no, vehicleid = acs.acs_vehicle_id } equals new { rfid = link.RfidNumber, vehicleid = link.VehicleID}
group new {acs,acsout } by new { link.RfidNumber, link.VehicleID, acs.Date } into group1
select new
{
group1.Key.RfidNumber,
group1.Key.VehicleID,
group1.Key.Date,
acs_min_datetime = group1.Min(y => y.acs.acs_datetime),
acs_max_datetime = group1.Max(y => y.acsout.acs_datetime)
};
Both versions of the Query are compiling, therefore syntactically correct, you just need to make modifications to suit your use case
Another way (in SQL and LINQ) would be to group the rows regardless of in/out operation, and then filter and min/max inside each group:
var ans = from acs in dbo.acs_transaction
join linking in dbo.PassLinkings on new { RfidNumber = acs.acs_rfid_no, VehicleID = acs.acs_vehicle_id } equals new { linking.RfidNumber, linking.VehicleID }
group acs by new { linking.RfidNumber, linking.VehicleID, acs.Date } into acsg
select new {
acsg.Key.RfidNumber,
acsg.Key.VehicleID,
acsg.Key.Date,
InTime = acsg.Where(acs => acs.acs_operations == "in").Min(acs => acs.acs_datetime),
OutTime = acsg.Where(acs => acs.acs_operations == "out").Max(acs => acs.acs_datetime)
};
In my LINQ to SQL testing with a similar database query, this generated a single SQL query.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.