Sha*_*eKm 39 linq database asp.net database-design entity-framework
我正在努力实现这里所解释的: 创建一个像facebook和gmail这样的线程私人消息系统,但我并不完全理解Joel Brown的答案.任何人都可以解释一下.
这是我的数据库表与样本数据的样子(我假设我为了演示目的正确地填充了它):

我需要显示一个基于LoginId的线程列表(最新的)在LINQ中查询的样子是什么?(我要问的是在一组消息线程中,在每个线程中给我一条最新消息) - 就像这样在facebook上完成.
我需要在消息线程(LINQ)中显示所有消息 - >就像它在Facebook上完成的那样,你点击消息,你会看到整个"对话".
请帮忙!谢谢
编辑 - >继续乔尔,这是正确的吗?

乔尔,我有点困惑,你能解释一下(评论/问题用粗体):
这里的想法是,每次用户启动一个全新的线程/消息时,它都会以THREAD表中的新记录开头.然后将用户添加为THREAD_PARTICIPANT,并将消息内容添加到MESSAGE,该MESSAGE指向包含THREAD.从MESSAGE到USER的FK表示消息的作者.
LoginId 1向LoginId2发送消息=>将新记录插入到MessageThread表中.此外,还会在MessageThreadId = 1,LoginId = 1(发件人)的MessageThreadParticipant记录中插入记录.并在Message表中插入一条新记录,MessageId = 1,MessageThreadid = 1,SenderLoginId = 1(正确??)
这是迭代后我所拥有的:

我想我很困惑,因为Loginid 2无法知道他有消息.?? 或者我可能需要在MessageThreadParticipant中插入2条记录?(发送者和接收者) - >这种方式都可以看到整个"对话"?
EDIT2: 乔,我想我能做到这一点:
SELECT
Message.MessageId, Message.CreateDate, Message.Body, Login.Username, Message.SenderLoginId
, (SELECT MessageReadState.ReadDate
FROM MessageReadState
WHERE MessageReadState.MessageId = Message.MessageId
) as ReadDate
FROM Message
INNER JOIN Login ON Message.SenderLoginId = Login.LoginId
INNER JOIN MessageThreadParticipant mtp on mtp.MessageThreadId = Message.MessageThreadId
AND ( Message.MessageId in
( SELECT Max(Message.MessageId)
FROM MessageThreadParticipant INNER JOIN Message
ON MessageThreadParticipant.MessageThreadId = Message.MessageThreadId
GROUP BY MessageThreadParticipant.MessageThreadId
)
)
Where mtp.LoginId = 2
ORDER BY Message.CreateDate DESC;
Run Code Online (Sandbox Code Playgroud)
如果我错了请纠正我:)
Joe*_*own 75
那么你为什么不问?:)
让我试着确定你对你的要求的理解.在我看来,你正在看一个线程列表(不是树)两个人之间的消息.我认为你可能想要允许更多人而不仅仅是两个人.这就像Facebook就像有人发布消息一样,然后任何数量的人都可以阅读它,然后开始添加评论.当您添加注释时,它会将您置于该线程中,并开始获取状态更新和电子邮件,告诉您线程中的活动等等.假设这就是你所追求的,那么我向Big Mike建议的架构并不完全是你想要的.
请考虑以下内容:

这里的想法是,每次用户启动一个全新的线程/消息时,它都会以THREAD表中的新记录开头.然后将用户添加为THREAD_PARTICIPANT,并将消息内容添加到MESSAGE,该MESSAGE指向包含THREAD.从MESSAGE到USER的FK表示消息的作者.
当用户阅读消息时,他们会在MESSAGE_READ_STATE表中获得一个条目,表明他们已明确或隐式地标记了读取的消息,具体取决于您的要求.
当有人对线程中的初始消息发表评论时,会添加第二个MESSAGE,其中FK返回到原始THREAD,并且回复作者(用户)被添加到THREAD_PARTICIPANT表中.因此,消息被一个,两个甚至更多的参与者添加到线程中.
要在任何线程中获取最新消息,只需将MESSAGE中的前1个按创建日期(或身份密钥)降序排序,其中消息FK是感兴趣的线程.
要获取用户的最近更新的主题,得到消息相关顶端1线程降序排序上,其中消息是在该用户是THREAD_PARTICIPANT线程创建日期.
我担心,如果不打破LinqPad,我就永远不能在LINQ中陈述这些东西.如果你无法从上面看到我的偏差,我可以用表定义和一些SQL来充实答案.请在评论中提问.
编辑:澄清要求和实施
澄清要求:最初我正在考虑公开发布的消息,并有机会进行评论,而Shane则更多地使用直接消息功能.在这种情况下,初始接收者需要在开始时包含在THREAD_PARTICIPANT表中.
为了清楚起见,我们在表格中添加几行.这是一个场景,(为纪念加拿大日):用户1 DM用户2询问有关啤酒会议的问题.用户2回答有关在哪里见面和用户1回答的问题.表格看起来像这样:(可能过于简化了)

编辑#2:访问SQL以获取线程中所有消息的列表,具有读取状态...
使用@ OP的模式,此SQL将获取给定线程中的消息列表,并指示给定用户是否已读取每条消息.消息是最近的第一个订单.
SELECT
Message.MessageId
, Message.CreateDate
, Message.Body
, Login.Username
, (SELECT MessageReadState.ReadDate
FROM MessageReadState
WHERE MessageReadState.MessageId = Message.MessageId
and MessageReadState.LoginId = 2) as ReadState
FROM (Message INNER JOIN Login ON Message.SenderLoginId = Login.LoginId)
WHERE (((Message.MessageThreadId)=10))
ORDER BY Message.CreateDate DESC;
Run Code Online (Sandbox Code Playgroud)
请注意,如果将其称之为公平,那就是通过子选择来获取读取状态.这是必要的,因为获取读取状态的部分标准要求使用外部连接无法满足的where子句.因此,您可以使用子选择来确定MessageReadState子表中所需的值(可能缺少).
编辑3:SQL用于获取给定用户的每个最新消息的所有线程...
要获取给定用户参与的所有线程的列表,首先按最新消息排序,仅显示最新消息(每个线程1条消息),那么您将使用与上述消息类似的查询,除了通过FK将消息过滤到感兴趣的线程之外,您可以通过子查询过滤消息,该子查询在感兴趣的用户参与的每个线程中查找最新消息.它将如下所示:
SELECT
Message.MessageId
, Message.CreateDate
, Message.Body
, Login.Username
, (SELECT MessageReadState.ReadDate
FROM MessageReadState
WHERE MessageReadState.MessageId = Message.MessageId
and MessageReadState.LoginId = 2) AS ReadState
FROM Message INNER JOIN Login ON Message.SenderLoginId = Login.LoginId
WHERE ( Message.MessageId in
( SELECT Max(Message.MessageId)
FROM MessageThreadParticipant INNER JOIN Message
ON MessageThreadParticipant.MessageThreadId = Message.MessageThreadId
WHERE MessageThreadParticipant.LoginId=2
GROUP BY MessageThreadParticipant.MessageThreadId
)
)
ORDER BY Message.CreateDate DESC;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25440 次 |
| 最近记录: |