У меня есть система чата, состоящая из 3 таблиц: Users, RoomJoins (закрытая беседа, к которой вы присоединились) и чатов (список сообщений чата с меткой времени).Entity Framework несколько типов объединения с датами, группами по и счету
Я хочу получить список всех частных комнат для данного пользователя, а затем число новых сообщений чата, которые он получил с момента последнего входа в систему.
SQL-запрос, который работает (возможно, может быть улучшена, но, конечно, работает) является:
select a.roomid, b.userid, m.firstpicurl, count(p.roomid) as cuenta from roomjoin a
inner join roomjoin b
on b.roomid=a.roomid and a.userid<>b.userid
inner join myuser m on m.id=b.userid
left join
chat p on p.roomid=a.roomid and p.sentwhen > a.lastseen
where a.userid=45 and a.active=1
group by a.roomid, b.userid, m.firstpicurl
, что в основном говорит: дайте мне все roomids (частные разговоры) для идентификатора пользователя = 45, а также идентификатор пользователя из человек, который прислал мне сообщение, его изображение и количество сообщений чата, где sentwhen> user.lastseen
результат будет что-то вроде
roomid userid firstpicurl cuenta
1 43 http://... 3
2 37 http://... 0
означая userid 43 отправил вам 3 сообщения с момента вашего последнего входа, в то время как пользователь 37 не отправил вам ничего нового
Теперь я пытаюсь перевести это в EF, и я вроде как его работаю, но проблема в том, что я не может найти способ запроса с использованием формата datewhen> lastseen date, поскольку он этого не позволяет. И если я попытаюсь с предложениями Where, я никогда не получу правильный ответ. Вот мой существующий попытка (без sentwhen> lastseen)
from a in db.RoomJoins.Where(c => c.userid == u.id && c.active == true).OrderBy(c => c.roomid)
from b in db.RoomJoins.Where(fp => fp.roomid == a.roomid && fp.userid != a.userid)
from m in db.Users.Where(m => b.userid == m.id)
join p in db.Chats on a.roomid equals p.roomid into j1
from j2 in j1.DefaultIfEmpty()
group j2 by new { a.roomid, b.userid, m.firstpicurl } into g
select new
{
roomid = g.Key.roomid,
userid = g.Key.userid,
firstpicurl = g.Key.firstpicurl,
count = g.Count()
};
мой код, кажется, работает, но есть 2 проблемы: 1) он не принимает во внимание временную метку, я просто хочу, счетчик сообщений после моего lastseen 2) Я получаю количество 1, когда он должен быть равен 0. Таким образом, я хотел бы получить что-то вроде этого
roomid userid firstpicurl cuenta
1 43 http://... 3
2 37 http://... 1 <-- this should be 0
кто-нибудь знает, как добиться того, что я ищу?
Первый ответ: Этот, похоже, работает, но выглядит очень сложным. Есть ли способ сделать проще?
from a in db.RoomJoins.Where(c => c.userid == 45 && c.active == true)
from b in db.RoomJoins.Where(fp => fp.roomid == a.roomid && fp.userid != a.userid)
from m in db.Users.Where(m => b.userid == m.id)
from p in db.Chats.Where(p => p.roomid==a.roomid &&
p.sentwhen > a.lastseen).DefaultIfEmpty()
select new
{
roomid = a.roomid,
userid = b.userid,
firstpicurl = m.firstpicurl,
cid = p.Id
} into j1
group j1 by new { j1.roomid, j1.userid, j1.firstpicurl } into g
select new
{
roomid = g.Key.roomid,
userid = g.Key.userid,
firstpicurl = g.Key.firstpicurl,
count = g.Count(e => e.cid!=null)
};
Что происходит, когда вы добавляете дополнительные присоединиться на ограничение на вступление заявление таблицы р? Как вы это делали в своем sql-запросе? –
, независимо от производительности, предложение 'Where' должно всегда работать. Это не работает, это означает, что ваш запрос LINQ неверен в какой-то другой точке. – Hopeless
Общие рекомендации, что я могу дать, не тратьте время на перевод SQL-запросов в EF. Это просто противодействует продуктивности без каких-либо дополнительных преимуществ. Я научился этому трудно в проекте, где я даже не мог контролировать схему базы данных, и каждый запрос занимал в 3 раза больше, чем писать: один раз в sql, который был знаком, второй в EF, а третий выясняет, почему все еще не работает. EF блестящий с простыми схемами, а также очень хорошо подходит для отслеживания изменений. Остальное вызовите SP. –