【问题标题】:Extend database for multi-tenant application为多租户应用程序扩展数据库
【发布时间】:2018-11-11 21:37:43
【问题描述】:

我们正在重建一个多租户 asp.net 网络应用程序,但我无法确定最合适的数据库结构。我已经阅读了大量关于 SO 和 Microsoft 多租户架构文章的问题/答案,但似乎找不到我正在寻找的信息。

该应用程序有 2 类最终用户:

  • 将公司信息输入数据库的供应商(地址、联系信息、保险金额等)
  • 雇佣供应商的公司。公司用户登录并查看供应商输入的数据。公司用户可以搜索供应商、生成报告等。

问题:

  • 使用该系统的每个公司都希望从供应商那里获得不同的信息。他们都想要地址和联系信息等基本信息,但有些人会想要一些仅适用于该公司的附加字段(特定保险信息或其他内容)。

我倾向于对数据库字段使用名称-值对,以便我们可以根据每个公司的需要扩展数据库。我的问题:

  • 鉴于上述信息以及名称-值将使查询/过滤供应商显着复杂化这一事实,这似乎是最佳方法吗?我正在考虑的另一个选择是为每个具有该特定公司所需字段的公司创建一个单独的“附加字段”表。

非常感谢您的输入/答案。

【问题讨论】:

  • 那么有多个公司,每个公司都有多个供应商?供应商可以属于多个公司吗?我过去设计过多租户系统,出于几个原因,我选择了每个客户一个数据库的路线。但我不确定它是否适合您的场景。
  • 没错。供应商选择他们最初尝试为哪个公司聘用,然后输入该公司所需的数据。如果供应商将来需要为其他公司工作,那么他们会返回并填写其他公司想要的任何缺失数据。

标签: sql-server multi-tenant


【解决方案1】:

我过去做过 EAV 解决方案,而且效果很好。如果我理解正确(供应商-公司关系是多对多/多对多),我认为这可能适用于您的情况。我在这里写过 EAV 的优缺点:

这是否适合您将取决于几件事。您提到的“附加字段”是相对固定的集合,还是按需添加?如果它们是一个相对固定的集合,那么您可以只使用一个访问(不是 Microsoft Access)表来说明每组列是否与该供应商-公司对相关。

CREATE TABLE dbo.Corporations
(
    CorporationID INT PRIMARY KEY,
    Name NVARCHAR(255) NOT NULL UNIQUE
    -- ... other columns ...
);

CREATE TABLE dbo.Vendors
(
    VendorID INT PRIMARY KEY,
    Name NVARCHAR(255) NOT NULL UNIQUE
    -- ... other columns ...
);


CREATE TABLE dbo.AdditionalColumnSets
(
    ColumnSetID INT PRIMARY KEY,
    Name NVARCHAR(255) NOT NULL UNIQUE -- e.g. Insurance
    -- ... other columns ...
);

CREATE TABLE dbo.AdditionalData
(
    VendorID INT, -- foreign key here
    ColumnSetID INT, -- foreign key here
    ColumnName NVARCHAR(255),
    ColumnValue NVARCHAR(2048),
    -- you may want to extend this to store string, number, date
    -- data differently
    PRIMARY KEY(VendorID, ColumnSetID, ColumnName)
);

CREATE TABLE dbo.AdditionalDataAccess
(
    CorporationID INT, -- foreign key here
    VendorID INT, -- foreign key here
    ColumnSetID INT, -- foreign key here
    HasAccess BIT NOT NULL DEFAULT (1),
    PRIMARY KEY(CorporationID, VendorID, ColumnSetID)
);

-- now, you can check for HasAccess in this table
-- you can also infer from lack of being in this table
-- whether that means they have access or they don't
-- have access to a particular column set.

-- ultimately, after you got hte base data from the
-- standard tables like Vendors, the query would look 
-- something like this, if presence in the 
-- AdditionalDataAccess table is required:

DECLARE @CorporationID INT = 1, @VendorID INT = 1;

SELECT
    ColumnName,
    ColumnValue
FROM
    dbo.AdditionalData AS ad
WHERE
    VendorID = @VendorID
    AND EXISTS
    (
        SELECT 1
            FROM dbo.AdditionalDataAccess
            WHERE ColumnSetID = ad.ColumnSetID
            AND CorporationID = @CorporationID
            AND VendorID = @VendorID
            AND HasAccess = 1
    );

-- you'll have to pivot or transform in the client to
-- see these as columns instead of rows

希望这是有用且有意义的。

【讨论】:

  • 我现在正在处理这样的设置。你知道这是什么鬼吗?正在搜索。一切都是 varchar。JOIN JOIN JOIN JOIN JOIN JOIN。“为什么搜索要花这么长时间?”纯粹的。地狱。
  • 如果您为每个实体使用代理项,您应该能够抽象出大部分 varchars - 从而实现更高效的连接。但这一切都取决于您需要如何搜索 - 每个实现都会有不同的最终结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-01
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 2018-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多