首先是背景。我们的应用程序基于ASP.NET MVC3,.NET 4.0,并使用Linq-to-Sql(PLINQO)作为其主要的数据访问方式。我们的Web应用程序是一个多租户/多客户端系统,每个客户端都有自己的Sql Server数据库。到目前为止,每个Sql Server数据库都具有完全相同的模式。
通常,客户会要求我们跟踪其他客户无法跟踪的自定义字段。我们处理这个问题的方法是在主表中保留db中的一些自定义字段。例如,我们的Widget表可能包含CustomText1,CustomText2 .. CustomText10和CustomDate1,CustomDate2..CustomDate10字段。同样,我们跨客户端的所有模式都是相同的,因此Linq-to-Sql像处理任何其他字段一样轻松地处理这些字段。
现在我们遇到了一个客户想要几百个CustomBool字段但不需要其他字段的问题。因此,基本上,我们正在研究仍然使用Linq-to-Sql的方法,但是根据它所连接的数据库,它可以针对可能不同的模式工作(尽管它们以非常具体的方式不同。)
已经在Linq-to-Sql上构建了太多的代码并访问了它生成的Widget类,我不想再回到直接的SQL。
我在这里和网上看到了Linq to Sql访问具有相同模式的不同表的方法的答案,但是我找不到具有不同列的不同dbs的相同表名的良好答案。 / p>
这可能吗?
答案 0 :(得分:1)
如果主要目标是为现有域对象存储一些额外字段,那么为什么不创建可以存储键值对的通用表。这非常灵活,因为如果客户需要新属性,则无需更改架构。
我们经常这样做,并且通常有一些助手来正确地施放属性,例如
Service.GetProperty<bool>("SomeCustomProperty")
如果您正在寻找一个可以为每个租户完全不同的“可插拔”域模型,我认为如果您遵循数据库驱动的方法并使用L2S设计器生成代码,您将会很困难。
要实现这一点,您需要根据代码(域驱动设计)生成数据库,这将为您提供更大的灵活性,即您可以在运行时加载特定于租户的配置(类集,业务规则等)并使用它来生成/验证您的架构。
如果您能详细说明您采用的设计方法,即使用Linq设计器并从数据库生成模型,那将是一件好事吗?
很明显,通用键值对存储不符合您的查询要求。
如果不提出不同的技术,很难提供解决方案。关系型SQL数据库并不适用于动态域模型。使用MongoDb或RavenDb等文档数据库可能会更好,因为您不依赖于特定架构。您甚至可以将仅用于自定义属性。
如果这不理想,那么另一种解决方案是使用类似Dapper的内容来构建查询。假设您正在开发针对接口的开发,您可以为每个租户实现一个使用其自定义字段的数据服务实现。
Ayende撰写了一系列关于多租户的帖子,涵盖了租户特定的域名模型。它开始here,可能对你有用。