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

发布于 2024-11-17 16:53:55 字数 544 浏览 2 评论 0原文

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

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

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

问题:

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

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

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

非常感谢输入/答案。

We're rebuilding a multi-tenant asp.net web app and I'm having trouble nailing down the most appropriate database structure. I've read loads of questions/answers on SO and the Microsoft multi-tenancy architecture article, but can't seem to find the info I'm looking for.

The application has 2 types of end users:

  • A vendor who inputs their company's information into the database (things like address, contact info, insurance amounts, etc.)
  • A corporation hiring the vendors. The corporation user logs in and views the data the vendor has entered. Corporation users can search vendors, run reports, etc.

Issue:

  • Each corporation that uses the system wants different information from the vendors. They all want basic info like address and contact info, but then some will want an abritrary number of additional fields (specific insurance info or something) that apply only to that corp.

My inclination is to use Name-Value pairs for the database fields so we can extend the database as needed for each corporation. My questions:

  • Does this seem like the best approach given the info above and the fact that name-value will significantly complicate querying/filtering vendors. The other option I'm considering is creating a separate "additional fields" table for each corporation that has the fields required by that particular corp.

Input/answers greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

2024-11-24 16:53:55

我过去曾做过 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

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

I've done EAV solutions in the past, and they work quite well. I think this could work for your situation if I understand it right (that the vendor-corporation relationship is many-to-many / all-to-many). I've written about the pros and cons of EAV here:

Whether this is appropriate for you will depend on a couple of things. Are the "additional fields" you mention a relatively fixed set, or are they added on demand? If they are a relatively fixed set, then you could just have an access (not Microsoft Access) table that tells whether each set of columns is relevant for that vendor-corp pair.

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

Hope this is useful and makes sense.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文