У меня есть пример базы данных, она содержит таблицы для фильмов, людей и кредитов.Таблица Movie содержит заголовок и идентификатор.Таблица People содержит имя и идентификатор.Таблица «Кредиты» связывает фильмы с людьми, которые работали над этими фильмами, в определенной роли.Таблица выглядит следующим образом:
CREATE TABLE [dbo].[Credits] (
[Id] [int] IDENTITY (1, 1) NOT NULL PRIMARY KEY,
[PersonId] [int] NOT NULL FOREIGN KEY REFERENCES People(Id),
[MovieId] [int] NOT NULL FOREIGN KEY REFERENCES Movies(Id),
[Role] [char] (1) NULL
В этом простом примере столбец [Роль] представляет собой один символ, по моему соглашению либо «А», чтобы указать, что человек был субъект в этом конкретном фильме или 'D' для режиссер .
Я хотел бы выполнить запрос для конкретного человека, который возвращает имя человека, а также список всех фильмовчеловек работал над ролями в этих фильмах.
Если бы я сериализовал его в json, он мог бы выглядеть так:
{
"name" : "Clint Eastwood",
"movies" : [
{ "title": "Unforgiven", "roles": ["actor", "director"] },
{ "title": "Sands of Iwo Jima", "roles": ["director"] },
{ "title": "Dirty Harry", "roles": ["actor"] },
...
]
}
Как я могу написать запрос LINQ-to-SQL, который формирует вывод таким образом?
У меня проблемы с эффективностью.
Попробуйте # 1
, если я использую этот запрос:
int personId = 10007;
var persons =
from p in db.People
where p.Id == personId
select new
{
name = p.Name,
movies =
(from m in db.Movies
join c in db.Credits on m.Id equals c.MovieId
where (c.PersonId == personId)
select new {
title = m.Title,
role = (c.Role=="D"?"director":"actor")
})
};
Я получаю что-то вроде этого:
{
"name" : "Clint Eastwood",
"movies" : [
{ "title": "Unforgiven", "role": "actor" },
{ "title": "Unforgiven", "role": "director" },
{ "title": "Sands of Iwo Jima", "role": "director" },
{ "title": "Dirty Harry", "role": "actor" },
...
]
}
Это не такСовершенно верно.Как вы можете видеть, есть дубликат каждого фильма, для которого Иствуд сыграл несколько ролей.Я ожидал бы этого, потому что в таблице кредитов есть несколько строк для этой комбинации фильм + человек, по одной для каждой роли.
Попробуйте # 2
Я думал, что я буду использовать группу по , вот так:
var persons =
from p in db.People
where p.Id == personId
select new
{
name = p.Name,
movies =
(from m in db.Movies
join c in db.Credits on m.Id equals c.MovieId
where (c.PersonId == personId)
orderby m.Year
group ((c.Role == "A")? "actor":"director")
by m.Id
into g
select new {roles = g })
};
Вывод довольноблизко к тому, что я хочу.Это выглядит так:
{
"name" : "Clint Eastwood",
"movies" : [
{ "roles": ["actor", "director"]},
{ "roles": ["director"]},
{ "roles": ["actor"]},
...
]
}
Это близко, но, конечно, у меня нет названий фильмов.
Попробуйте # 3
Если я использую группу по и добавлю название фильма, например:
var persons =
from p in db.People
where p.Id == personId
select new
{
name = p.Name,
movies =
(from m in db.Movies
join c in db.Credits on m.Id equals c.MovieId
where (c.PersonId == personId)
orderby m.Year
group ((c.Role == "A")? "actor":"director")
by m.Id
into g
select new { title = m.Title, roles = g })
};
...то не скомпилируется из-за
ошибки CS0103: имя 'm' не существует в текущем контексте
Как мне сформироватьвыход так, как я хочу?