c# - 选择所有带有所有标签的帖子

标签 c# sql .net sql-server dapper

关于这个有很多问题,但没有足够明确的答案,尤其是在这种情况下使用 SQL Server。

我有 3 个表来表示博客文章和与之关联的标签。我想运行一个查询来获取所有帖子和每个帖子标签——我需要标签 ID 和名称。结果需要很容易序列化到我的 C# 类中。我也在尝试使用 Dapper.net 但这不是最重要的部分。

显然很多网站都这样做,我想知道最好的方法以及在现实世界中应该如何做?我可以获得所有帖子,然后对每个帖子运行多个查询,然后返回每个帖子的标签。但肯定有更好的方法吗?

如果我只是想获得一个帖子,那么我会写多个选择。一个用于帖子,一个用于标签。但我想要所有的帖子。有没有一种方法可以在不为返回的每个标签行复制发布信息的情况下执行此操作?

例如,如果每个帖子的标签都序列化到一个以逗号分隔的列中,那么如何才能同时获得 ID 和名称?编码字符串?

SELECT * FROM dbo.Posts    
SELECT * FROM dbo.Tags
SELECT * FROM dbo.PostTags

Posts
Id  Title       Content
===============================
1   First Post  First Content
3   Second      Second Content

Tags
Id  Name
============
1   C#
2   SQL
3   IIS
4   Steam
5   OpenID

PostTags
PostId  TagId
=============
1       1
1       2
3       3
3       4

只需使用以下查询连接表:

SELECT p.*, t.Name
FROM dbo.Posts p
LEFT JOIN dbo.PostTags pt ON p.id = pt.PostId
LEFT JOIN dbo.Tags t ON t.id = pt.TagId

通过为与其关联的每个标签重复帖子内容来提供大量冗余数据:

Id  Title       Content         Name
======================================
1   First Post  First Post      C#
1   First Post  First Post      SQL
3   Second Post Second Content  IIS
3   Second Post Second Content  Steam

最佳答案

这纯粹是一个练习,让我先声明被复制的数据量很可能不是什么大问题。尽管如果帖子非常大并且数量很多,那么避免重复确实开始变得更有意义。

此外,使用 C# Linq-to-Sql 或 Entity Framework ,将为您和您的 Post 计算出对象关系。实体将有一个 List<Tag>您可以访问的属性。

但是,如果您想滚动自己的类型,一个只涉及一次数据库往返且不重复数据的选项是编写一个存储过程,让您返回 2 个记录集(2 个单独的选择语句)- 一个带有发布内容,一个带标签的内容。

然后创建一个表示 Post 的 C# 类将非常简单并且只有一个 List<Tag>并从存储的过程结果中提取它。

Create Procedure GetPostTags
As

-- We will use the GotTags column here to loop through and get tabs later
Declare @Posts Table (
    PostID varchar(50), 
    PostTitle varchar(50), 
    PostContent varchar(50),
    GotTags bit default 0
)

/* Assuming you care about the ID's, this will get you all of 
   the tags without duplicating any post content */
Declare @PostTags Table (
    PostID int,
    TagID int,
    TagName varchar(50)
)

-- Populate posts from the main table
Insert Into @Posts (PostID, PostTitle, PostContent)
Select * From Posts

-- Now loop through and get the tags for each post. 
Declare @CurrentPostID int
Set @CurrentPostID = (Select Top 1 PostID From @Posts Where GotTags = 0)
While @CurrentPostID Is Not Null
    Begin
        Insert Into @PostTags (PostId, TagID, TagName)
        Select pt.postid, pt.tagid, t.name
        From Tags t 
            Join PostTags pt
                On t.id = pt.tagid
        Where pt.postid = @CurrentPostID

        -- Set next loop
        Update @Posts Set GotTags = 1 Where PostID = @CurrentPostID
        Set @CurrentPostID = (Select Top 1 PostID From @Posts Where GotTags = 0)
    End

-- Return 2 recordsets, which are related by the PostID column found in both sets
Select * from @Posts
Select * From @PostTags

我更喜欢这种类型的解决方案,而不是将字符串连接成一个字符串,然后再将它们拆分;它使以这种方式处理数据变得更容易,允许在 C# 中更加面向对象,并且让您更容易跟踪标签 ID,以防标签需要从帖子中删除或添加,您不需要查找标签或按名称匹配,因为您已经有了 ID。

关于c# - 选择所有带有所有标签的帖子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21767613/

相关文章:

javascript - 从 List<string> C# 填充 JS 数组

c# - 如何设置表格列的宽度限制?

c# - AES 托管提供程序默认值

c# - 具有属性但没有逻辑单元可测试的类吗?

.net - 如何解析 DateTime 并将其转换为 RFC 822 日期时间格式?

c# - 在并行循环中使用 SMO 从 .net 中的 SQL Server 数据库编写对象定义脚本

c# - 如何反转颜色?

php - 存储 SQL 结果以在其他网页上使用

sql - 在 oracle 的 join select 查询中将某些列名称别名为一个字段

java - 我如何将 Intent 方法插入到此代码中,以便单击按钮时它将显示第二个 Activity