为多租户应用程序扩展数据库

时间:2011-06-30 15:48:46

标签: sql-server multi-tenant

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

该应用程序有两种类型的最终用户:

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

问题:

  • 使用该系统的每个公司都需要来自供应商的不同信息。他们都想要地址和联系信息等基本信息,但是有些人会想要一些仅适用于该公司的额外字段(特定保险信息或其他内容)。

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

  • 考虑到上述信息以及名称值将使查询/过滤供应商复杂化这一事实,这看起来是最好的方法。我正在考虑的另一个选择是为每个公司创建一个单独的“附加字段”表,其中包含该特定公司所需的字段。

输入/答案非常感谢。

1 个答案:

答案 0 :(得分: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

希望这是有用的,也是有道理的。