#c# #linq #group-by
#c# #linq #группировать по
Вопрос:
Я хочу создать набор данных для отображения древовидного представления со всем автопарком, который есть у одного пользователя, и всеми автомобилями каждого автопарка
Итак, дерево должно выглядеть следующим образом
|
| - fleetName -- fleet_id as node key
| |
| |--- plate_number -- gps_device_id as node key
| - plate_number -- for cars wont belong to any fleet
customer_cars
CREATE TABLE tracker.customer_cars
(
customer_car_id integer NOT NULL DEFAULT nextval('customer_cars_car_id_seq'::regclass),
gps_device_id integer,
plate_number string
user_id text NOT NULL,
fleet_id integer,
CONSTRAINT customer_cars_idx PRIMARY KEY (customer_car_id),
CONSTRAINT cars_gps_device_fk FOREIGN KEY (gps_device_id)
REFERENCES tracker.gps_devices (gps_device_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fleet_fk FOREIGN KEY (fleet_id)
REFERENCES tracker.fleet_cars (fleet_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
fleet_cars
CREATE TABLE tracker.fleet_cars
(
fleet_id serial NOT NULL,
fleet_name text,
user_id text NOT NULL,
CONSTRAINT fleet_idx PRIMARY KEY (fleet_id)
)
Что я пытаюсь
var customer_cars = db.customer_cars
.Include(c => c.gps_devices)
.Include(c => c.fleet_cars)
.Where(c => c.user_id.CompareTo(UserId) == 0)
.GroupBy(c => c.fleet_id,
c => c.fleet_cars,
(key, g) => new
{
FleetID = key,
Cars = g.ToList()
}
);
Но его нет fleet_name
, только fleet_id
, а в машинах есть customer_cars
строки без gps_device_id
foreach (var fleet in customer_cars)
{
-- have id but no name
string fleet_id = fleet.FleetID.HasValue ? fleet.FleetID.ToString() : "0";
foreach (var car in fleet.Cars ){
string fleet_name = car.fleet_name; -- have fleet_name
string gps_id = car.gps_device_id ; -- dont have gps_device_id
}
}
Комментарии:
1. Попробуйте : .GroupBy(c => new {c.fleet_id, c.fleet_cars}). Чтобы получить name, вам нужно объединить две таблицы по идентификатору.
2. @jdweng в этом случае
fleet in customers_cars
является коллекцией, а не объектом fleet. Я должен былfleet = {fleet_id, fleet_name, list<cars>}
3. Я сказал, что вам нужно использовать объединение. Смотрите msdn : code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
4. @jdweng Проблема заключалась в том, что я удалил
SELECT
часть, когда изменение на вашеGROUP BY
сейчас работает нормально. Спасибо
Ответ №1:
Немного изменив свою группу по ключу, вы получите то, что хотите:
var customer_cars = db.customer_cars
.Include(c => c.gps_devices)
.Include(c => c.fleet_cars)
.Where(c => c.user_id.CompareTo(UserId) == 0)
.GroupBy(c => new { c.fleet_id, c.fleet_cars})
.Select(gr => new
{
FleetID = gr.Key.fleet_id,
FleetName = gr.Key.fleet_cars.fleet_name,
Cars = gr.ToList()
});
Комментарии:
1. Это намного лучше. Теперь просто нужно название флота.
2. @JuanCarlosOropeza Привет, ты отредактировал мой ответ. Вы имеете в виду, что это то, что вы хотите, и это сработало или не сработало?
3. Да, я только что протестировал это и обнаружил сам. Теперь проверяем, получен ли правильный результат.
4. @JuanCarlosOropeza Allrgiht
5. @JuanCarlosOropeza Конечно. По сути, в вашей реализации содержимое групп, которые были созданы на основе c.fleet_id, содержало соответствующие fleet_cars для каждого fleet_id. В то время как в этой версии группировка основана как на fleet_id, так и на fleet_cars. Для подробного объяснения GroupBy, если у вас есть время, прочитайте это codeblog.jonskeet.uk/2011/01/01 /… принесло бы дивиденды.