#c# #entity-framework #linq #linq-to-sql
#c# #сущность-фреймворк #linq #linq-to-sql
Вопрос:
У меня есть функция, которая требует возврата всех пользователей, за исключением тех, которые были удалены, я написал следующий запрос
var userLists = await _repositoryContext.User
Join(_repositoryContext.Eliminations,
u => currentUser.userID,
m => m.userOneId,
(u, m) => new { Eliminations = m, Users = u })
.Where(u_m => u_m.Users.userID != currentUser.userId amp;amp; u_m.Eliminations.userTwoId != u_m.Users.userID).Select(u_m => u_m.Users).ToListAsync();
Вот как будет выглядеть таблица пользователя
userID: cf321a6a-70de-45c9-997d-de7d2be99a36
name: test1
email: test1@gmail.com
-------------------------------------------------------------
userID: b1b2f69a-2100-499b-a0e6-42bbf87290ee
name: test2
email: test2@gmail.com
-------------------------------------------------------------
userID: b2be45d2-f065-4321-842d-cc35d29c374f
name: test3
email: test3@gmail.com
-------------------------------------------------------------
Этот запрос отлично работает, когда таблица исключений выглядит следующим образом
userMatchID: 7b2bc383-a818-4662-8f62-4f407650da9e
userOneWin: 1
userTwoWin: 0
userOneId: cf321a6a-70de-45c9-997d-de7d2be99a36
userTwoId: b2be45d2-f065-4321-842d-cc35d29c374f
Когда test3 user
находится в таблице исключений, запрос работает нормально и возвращает test2 user
userID: b1b2f69a-2100-499b-a0e6-42bbf87290ee
name: test2
email: test2@gmail.com
Но когда test2 user
добавляется в таблицу исключений, как показано ниже
userMatchID: 7b2bc383-a818-4662-8f62-4f407650da9e
userOneWin: 1
userTwoWin: 0
userOneId: cf321a6a-70de-45c9-997d-de7d2be99a36
userTwoId: b2be45d2-f065-4321-842d-cc35d29c374f
--------------------------------------------------------------
userMatchID: b9be0fd3-7e4f-4311-901e-c28715ee13d1
userOneWin: 1
userTwoWin: 0
userOneId: cf321a6a-70de-45c9-997d-de7d2be99a36
userTwoId: b1b2f69a-2100-499b-a0e6-42bbf87290ee
запрос завершается ошибкой и отправляет обоих доступных в данный момент пользователей вместо отправки пустого списка.Который выглядит следующим образом
-------------------------------------------------------------
userID: b1b2f69a-2100-499b-a0e6-42bbf87290ee
name: test2
email: test2@gmail.com
-------------------------------------------------------------
userID: b2be45d2-f065-4321-842d-cc35d29c374f
name: test3
email: test3@gmail.com
-------------------------------------------------------------
Но результат, который я хочу, — это пустой список без записей, test1 user
который в любом случае опущен в запросе Linq. Я что-то делаю не так?
Комментарии:
1. Неясно, что вы возвращаете и чего ожидаете. Из того, что я прочитал о том, как вы структурировали запрос с помощью объединения, похоже, что вы вернете две ссылки на идентификатор пользователя: cf321a6a-70de-45c9-997d-de7d2be99a36, что, вероятно, не то, что вы ожидаете.
2. @StevePy Я обновил вопрос с результатами на каждом этапе и ожидаемым результатом
Ответ №1:
Я сомневаюсь, что это сработает, потому что это не так, как вы сделали бы это в обычной базе данных. Если у вас было два списка пользователей, вы не можете ответить «каких из этих пользователей нет в этом списке» исключительно внутренним соединением — объединяя их всех вместе и запрашивая работу this.userid != that.userid
wil, когда в «этом» списке есть только один пользователь, но как только вы добавите два, вы получитевсе пользователи из «этого» списка, потому что каждый из них не равен хотя бы одному из пользователей из этого списка
This
A
B
That
A
Возвращается только B, потому что B != A, (и A == A)
This
A
B
C
That
A
B
A возвращается, потому что A != B, B возвращается, потому что B != A, C возвращается дважды, потому что C != A и C != B
Короче говоря, не используйте для этого inner join. Посмотрите на шаблон, больше похожий
var elim1 = DbContext.Eliminations.Where(e => !e.UserOneWin).Select(e => e.UserOneId);
var elim2 = DbContext.Eliminations.Where(e => !e.UserTwoWin).Select(e => e.UserTwoId);
DbContext.Users.Where(u => !elim1.Any(e => e.UserOneId == u.UserId) amp;amp; !elim2.Any(e => e.UserTwoId == u.UserId))
Это должно быть сопоставлено с sql, более похожим на
Users u
WHERE
NOT EXISTS (SELECT null FROM eliminations WHERE u.UserId = userOneId) AND
NOT EXISTS (SELECT null FROM eliminations WHERE u.UserId = userTwoId)
EXISTS лучше подходит для ответа на этот вопрос, чем внутреннее соединение. В качестве альтернативы вы могли бы внутренне присоединить пользователей к отдельным победителям, а не к проигравшим. Честно говоря, я не думаю, что ваш дизайн стола приносит вам здесь какую-то пользу. У меня были бы исключения, сопоставляющие winninguserid и losinguserid, а не user one и user two и еще один столбец, чтобы сказать, выиграл ли пользователь, и еще один столбец, чтобы сказать, проиграл ли пользователь. На данный момент каждый раз, когда вам нужен «список победителей» или «список проигравших», вы должны дважды попасть в таблицу отсева, эффективно объединяя всех пользователей, где winner1 имеет значение true, в userTwo, где winner2 имеет значение true, что намного неудобнее, чем просто иметь идентификатор победителя и идентификатор проигравшего колонка
Комментарии:
1. Я понял, что это может быть сложно сделать, когда записи продолжают накапливаться, поэтому на данный момент я решил добавить функцию в кодовую базу для сравнения и удаления пользователей из списка