首页 > 解决方案 > 我应该如何处理一对多关系来填充数据模型

问题描述

在使用数据在 C# 中构建模型时,我正在尝试确定如何处理我的数据库中的一对多关系。理想情况下,我想对数据库进行一次调用。但是,似乎可能需要两个(或更多)调用。

为简单起见,假设我的表看起来像这样......

CREATE TABLE [dbo].[Users]
(
    [userId] INT PRIMARY KEY IDENTITY(0,1),
    [userName] NVARCHAR(500) NOT NULL
)

CREATE TABLE [dbo].[Tasks]
(
    [taskId] INT PRIMARY KEY IDENTITY(0,1),
    [description] NVARCHAR(1000) NOT NULL,
    [userId] INT FOREIGN KEY REFERENCES [dbo].[Users](userId)
)

所以每个用户可以有很多任务。我有一个存储过程将返回用户的详细信息,看起来像这样......

CREATE PROCEDURE [dbo].[sp_GetUserDetail]
    @userId INT
AS
BEGIN
    SELECT
        [dbo].[Users].[userName] AS 'User',
        [dbo].[Tasks].[description] AS 'Task Description'
    FROM
        [dbo].[Users]
    INNER JOIN
        [dbo].[Tasks]
    ON
        [dbo].[Tasks].[userId] = [dbo].[Users].[userId]
    WHERE
        [dbo].[Users].[userId] = @userId
END

此过程返回与分配给用户的任务一样多的行。我试图填充的模型看起来像这样。

public interface User
{
    string Name { get; set; }
    List<string> Tasks { get; set; }
}

我看到我的选择如下:

  1. 使用此代码,并遍历从数据库返回的行以构建任务列表。
  2. 调用一个存储过程从用户表中返回数据,然后调用另一个从任务表中获取数据。
  3. 让单个存储过程返回单行中的所有数据的某些(我不知道的魔术)方法。
  4. 其他一些我什至不知道的选择。

经验丰富的开发人员通常如何处理此问题?

标签: c#sqldatabasestored-procedures

解决方案


有一些特定于语言/框架的答案我不会涵盖(因为 C# 不是我的强项),但值得一看“数据绑定”,这是 .Net 框架的特性之一。您还可以查看C# 的 ORM 工具

您给出的示例 - “我如何为我的父母加载子信息” - 很常见,您必须权衡数据库查询的数量与每个查询返回的数据量以及用户界面代码的复杂性。例如,如果任务具有子任务的外键(即自连接)、task_type 和 project_id,则您可以:

  • 每个表 1 个查询(您的选项 1):在 UI 层中实现最简单,在数据库层中实现最简单,但每个屏幕很容易导致数十次数据库调用。
  • 1 查询以检索屏幕的所有数据(您的选项 2):单个数据库命中,因此应该更快,但 UI 和数据库逻辑复杂;如果您继续遵循外键关系,则可能会将整个数据库加载到内存中。并非所有数据对于屏幕都是必需的。

对此没有“正确”的答案——这实际上取决于您的应用程序设计。

但是,有一个您没有提到的选项(这是特定于 SQL Server 的):存储过程可以返回多个结果集。因此,您可以有一个结果集来提供“标题”数据(用户信息),一个结果集来提供任务信息。


推荐阅读