我必须构建一个查询来获取未收到的用户并提醒新帖子。
我的相关表格结构如下:
帖子:postId int 用户:userId int,email varchar PostAlertUsers:postAlertUserId int,postId int,userId int
所有相关字段在表之间都有FK约束。
我在SQL中构建了这个查询,但找不到在Entity Framework中工作的方法:
SELECT u.email
FROM Users u
INNER JOIN Posts p ON p.userId != u.userId
LEFT JOIN PostAlertUsers pu ON u.userId = pu.userId AND p.postId = pu.postId
WHERE pu.postAlertUserId IS NULL
我写了以下EF查询,但没有得到相同的结果:
from u in context.Users
join pu in context.PostAlertUsers on u.userId equals pu.userId into postAlerts
from pa in postAlerts.DefaultIfEmpty()
join p in context.Posts on pa.postId equals p.postId
where pa.userId != u.userId
select u.email;
如何使用linq实体获得相同的结果。使用点语法(我不知道DbSet.Where(x => ...)
语法的正确术语)会更好。
修改
我希望PostAlertUsers
中Post
的{{1}}内没有Posts
的记录的所有用户都不是来自同一用户。
编辑2:
试图澄清一点:
我想警告用户每个帖子只有一次来自其他用户的新帖子,我的例程会每小时运行一次,检查是否有人发送消息。
我想让所有尚未收到有关帖子警告的用户因此在PostAlertUsers
上没有该用户和帖子组合的记录,但会在其他用户的帖子上有记录
示例数据:
Users
------------------------
userid | email
------------------------
1 | email1@test.com
2 | email2@test.com
3 | email3@test.com
------------------------
Posts (posts are created by users)
------------------------
postId | userId
------------------------
1 | 1
2 | 3
3 | 1
------------------------
PostAlertUsers (every time a user is notified about a new post, one record is added here)
------------------------
postId | userId
------------------------
1 | 2
1 | 3
2 | 1
------------------------
生成的查询将输出以下数据:
Result (using postId and userId to identify what user have to be notified for what post)
---------------------------------
postId | userId | email
---------------------------------
2 | 2 | email2@test.com
3 | 2 | email2@test.com
3 | 3 | email3@test.com
---------------------------------
修改
感谢AD.Net,我提出了以下建议:
from u in context.Users
let posts = contexto.Posts.Where(p => p.userId != u.userId)
from p in posts
join pau in context.PostAlertUsers on u.userId equals pau.userId
into alerts
from a in alerts.DefaultIfEmpty()
where a == null || a.postId != p.postId
orderby p.idPost
select new {
p.postId,
u.userId,
u.email
}
答案 0 :(得分:1)
编辑:
从不同角度进行的另一次尝试,不确定性能,可能与cross-join
from p in context.Posts
let otherUsers = context.Users.Where(u => u.UserId != p.User.UserId)
from u in otherUsers
join pau in alerts on u.UserId equals pau.User.UserId into alert
from a in alert.DefaultIfEmpty()
where a == null || a.Post.PostId != p.PostId
select new {p.PostId, u.Email};
这是LinqPad的尝试:
void Main()
{
var users = new List<User>{new User{UserId = 1}, new User{UserId = 2}};
var posts = new List<Post>
{
new Post{PostId = 1, User = new User{UserId = 2}},
new Post{PostId = 2, User = new User{UserId = 1}},
new Post{PostId = 3, User = new User{UserId = 2}},
};
var alerts = new List<PostUserAlert>
{
new PostUserAlert{Post = new Post{PostId = 1},
User = new User{UserId = 1}}
};
var result = (from p in posts
let otherUsers = users.Where(u => u.UserId != p.User.UserId)
from u in otherUsers
join pau in alerts on u.UserId equals pau.User.UserId into alert
from a in alert.DefaultIfEmpty()
where a == null || a.Post.PostId != p.PostId
select new {p.PostId, u.UserId}).ToList();
result.Dump();
}
class User
{
public int UserId { get; set; }
public string Email { get; set; }
}
class Post
{
public int PostId { get; set; }
public User User { get; set; }
public List<PostUserAlert> PostUserAlerts { get; set; }
}
class PostUserAlert
{
public Post Post { get; set; }
public User User { get; set; }
}
// Define other methods and classes here