1

我们有一个数据层,其中包含由数据库的输出(表/视图/procs/函数)生成的类。数据库中的表是规范化的,其设计类似于 OOP 设计(“发票”表与“文档”表具有 1:1 关系,“发票项”表与“文档项”表具有 1:1 关系“等...”。所有对/从数据库的访问都是通过存储过程(也适用于简单表)。

典型的类看起来像(很快):

public class DocumentItem {
    public Guid? ItemID { get; set; }
    public Guid? IDDocument { get; set; }
    public DateTime? LastChange { get; set; }
}

public class InvoiceItem : DocumentItem {
    public Guid? IDProduct { get; set; }
    public decimal? Price { get; set; }
}

问题是,数据库表的关系类似于 OOP 中的多重继承。现在我们为每个数据库输出创建一个新类。但是每个数据库输出都是数据库中“纯”表的组合。

理想的解决方案是(恕我直言)将类转换为接口,使用接口的多个实现,然后自动实现成员(这个“表类”只有属性,属性的主体总是相同的)。

例如:公共接口 IItem { Guid? 项目 ID { 获取;放; } 约会时间?上次更改 { 获取;放; } }

public interface IDocumentItem : IItem {
    Guid? IDDocument { get; set; }
}

public interface IItemWithProduct : IItem {
    Guid? IDProduct { get; set; }
}

public interface IItemWithRank : IItem {
    string Rank { get; set; }
}

public interface IItemWithPrice : IItem {
    decimal? Price { get; set; }
}

// example of "final" item interface
public interface IStorageItem : IDocumentItem, IItemWithProduct, IItemWithRank { }

// example of "final" item interface
public interface IInvoiceItem : IDocumentItem, IItemWithProduct, IItemWithPrice { }

// the result should be a object of class which implements "IInvoiceItem"
object myInvoiceItem = SomeMagicClass.CreateClassFromInterface( typeof( IInvoiceItem ) );

该数据库包含大量表,整个解决方案由动态加载的模块(100 多个模块)组成。

您认为什么是最好的方法,如何处理?

编辑:

使用部分类是一个很好的提示,我们解决方案中的芽不能使用,因为“IDocumentItem”和“IItemWithPrice”(例如)在不同的程序集中。

现在,如果我们在“DocumentItem”表中进行更改,我们必须在所有依赖程序集中重新生成源代码。几乎没有重用(因为不能使用多重继承)。如果有几十个依赖程序集,它会非常耗时。

4

4 回答 4

2

我认为从数据库模式自动生成域模型是个坏主意。

于 2009-05-06T21:33:49.337 回答
1

如果您希望继续从数据库自动生成并希望对多重继承进行建模,那么我认为您的想法是正确的:更改工具以输出具有多重继承的接口,以及 X num 实现。

您在其他地方指出了继承与聚合的约定,并且(据我了解)您确切知道生成的接口和类的外观。我知道业务规则在其他地方实现(可能在业务规则引擎中?),因此重新生成类不需要更改依赖代码,除非您想利用这些更改,或者现有属性已被更改或删除。

但你不会完成的。您的类仍将具有相关实体的 id。如果您想让客户端代码更容易,您应该引用相关实体(不关心相关实体的 ID),如下所示:

public class Person{
    public Guid? PersonID { get; set; }
    public Person Parent { get; set; }
}

这将使客户端的事情变得更容易。当您考虑时,从 ID 到引用是您无论如何都必须做的工作;最好在中间层做一次,而不是让客户做 N 次。另外,这使您的代码不那么依赖数据库。

所以最重要的是,我建议为自动生成的类编写一个 OO 包装器。您将针对几乎所有内容针对此 OO 包装器进行编程;只让数据访问层与自动生成的类交互。当然,您不能在数据库中重用继承元数据(我假设是通过约定指定的?),但至少您不会开辟新的道路。

相比之下,您现在拥有的数据模型看起来像一个贫乏的数据模型或更糟。

于 2010-07-28T18:14:15.153 回答
1

所以,你真的在​​寻找某种混合技术。当然,我不得不问你为什么不使用 LINQ to Entity Framework 或 NHibernate。O/RM 通过将关系模型映射到可用的数据结构来处理这些问题,这些数据结构具有 API 来支持您在数据库中操作数据所需的所有事务。但我离题了。

如果您真的在寻找一种混合技术来进行动态代码生成,请查看Mono Project 中的 Cecil。这是一个比尝试使用 Reflection.Emit 构建动态类更好的起点。还有其他动态代码生成器,但您可能想从 Cecil 开始,因为文档非常好。

于 2009-05-06T21:31:30.030 回答
0

我不清楚这种情况。

如果生成了代码,则不需要任何魔法:将一些元数据添加到标记“基本”接口的数据库对象(例如 SQL Server 中的扩展属性),并修改生成模板/工具以考虑这些标记。

如果问题是关于多重继承,那么您对.Net 不走运。

如果生成了代码,您还可以利用部分类和方法(您使用的是 .Net 3.5 吗?)在不同的源文件中生成代码。

如果您需要在运行时生成代码,有很多技术,尤其是 ORM 工具。

现在您可以更明确地说明您的设计背景吗?

于 2009-05-06T23:47:35.473 回答