【问题标题】:Linq 2 Sql and Dynamic table schemasLinq 2 Sql 和动态表模式
【发布时间】:2011-09-19 18:22:46
【问题描述】:

首先是背景。我们的应用程序基于 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 访问具有相同架构的不同表的方法的答案,但我还没有找到跨具有不同列的不同数据库的相同表名的好的答案。

这可能吗?

【问题讨论】:

    标签: linq-to-sql


    【解决方案1】:

    如果主要目标是为现有域对象存储一些额外的字段,那么为什么不创建一个可以存储键值对的通用表。这非常灵活,因为如果客户需要新属性,则无需更改您的架构。

    我们经常这样做,通常有一些帮助程序来正确转换属性,例如

    Service.GetProperty<bool>("SomeCustomProperty")

    如果您正在寻找一个更“可插入”的域模型,它可以为每个租户完全不同,我认为如果您遵循数据库驱动的方法并使用 L2S 设计器来生成您的代码,那么您将会遇到困难。

    要实现这一点,您确实需要根据您的代码(域驱动设计)生成数据库,这将为您提供更大的灵活性,即您可以在运行时加载特定于租户的配置(类集、业务规则等)并使用它来生成/验证您的架构。

    更新

    如果您能详细说明您所采用的设计方法,即您是否使用 Linq 设计器并从数据库生成模型,那就太好了?

    很明显,通用键值对存储无法满足您的查询要求。

    如果不建议不同的技术,很难提供解决方案。关系 SQL 数据库并不真正适合动态域模型。使用不依赖于特定模式的文档数据库(例如 MongoDbRavenDb)可能会更好。您甚至可以将这些仅用于您的自定义属性。

    如果这不理想,那么另一种解决方案是使用 Dapper 之类的东西来构建您的查询。假设您正在针对接口进行开发,您可以为每个租户实现您的数据服务,并使用他们的自定义字段。

    Ayende 发表了一系列关于多租户的文章,涵盖了租户特定的域模型。它以here 开头,可能对您有用。

    【讨论】:

    • 谢谢。是的,我们考虑使用键/值对表来提供无限数量的自定义字段。问题是 Linq2Sql 不能很容易地处理这个问题——例如,用于过滤和排序。因为这些是特定于客户端的字段,所以我们使用 Dynamic Linq-2-sql 库来执行以下操作:query = query.Where("CustomBool10=true and CustomCode2.Code=\"NY\"").OrderBy("CustomCode2.代码”)。 Linq2Sql 很乐意将这些转换为正确的 Sql 语句以获取客户端的列表。
    • @Linus 您可以使用 Linq 轻松查询,例如Where(p => p.PropertyName == "CustomBool10" && p.PropertyValue == 'true').OrderBy(p => p.PropertyValue)。如果您需要强类型查询,那么这可能不是您的最佳解决方案,因此您可能希望查看动态模型,尽管这确实取决于您的设计方法(如我的回答中所述)
    • 我知道您可以查询键值表,但是,查询变得更加复杂,因为它是一个逻辑记录的多行。例如,像“CustomDate10>CustomDate12”这样的查询是一个更难编写的查询,而且我们已经在使用这些类型的查询,动态 Linq-2-sql 非常容易处理。
    • 我们通常构建数据库模式,并使用 PLINQO 生成模型(实际上只是底层的 LINQ-to-SQL。)问题实际上归结为 Linq-to-Sql 对 1 施加的限制-1 映射。例如,如果我可以将 CustomText1..N 映射到一个数组,我们就可以了。无论如何,现在我们正在为数据库添加更多字段。如果我们以后需要解决这个问题,我们可以考虑其他解决方案,比如 Dapper,或者甚至可能只是简单的 ADO.NET,但很明显,我们在使用 Linq-to-SQL 时遇到了困难。感谢您的建议。
    猜你喜欢
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-03
    相关资源
    最近更新 更多