动态类创建

时间:2009-05-06 16:39:53

标签: c# .net dynamic-data

我们有一个数据层,它包含来自数据库的输出(tables / views / procs / functions)生成的类。数据库中的表是标准化的,其设计类似于OOP设计(“发票”表与“文档”表有1:1关系,“invoice-item”表与“document-item”表有1:1关系“等等...”。对数据库的所有访问都是通过存储过程(对于简单的表)。

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

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中的多重继承。现在我们为每个数据库输出创建一个新类。但是每个数据库输出都是数据库中“纯”表的组合。

理想的解决方案是(IMHO)转换类进行接口,使用接口的多个实现,然后自动实现成员(这个“table-classes”只有属性,属性体总是相同的)。 / p>

例如:     public interface IItem {         GUID? ItemID {get;组; }         约会时间? LastChange {get;组; }     }

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多个模块)组成。

您如何看待,最好的方式,如何处理它?<​​/ p>

修改

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

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

4 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

您在其他地方指出了强制执行继承与聚合的约定,并且(据我所知)您确切知道生成的接口和类应该如何显示。我理解业务规则是在其他地方实现的(可能在业务规则引擎中?),因此重新生成类不应该要求更改依赖代码,除非您想要利用这些更改,或者已经更改或删除了现有属性。 / p>

但你不会这样做。您的课程仍将包含相关实体的ID。如果您想让客户端代码更容易,您应该引用相关实体(不关心相关实体的ID),如下所示:

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

这会让客户端变得更容易。当你想到它时,从ID到引用是你必须要做的工作;最好在中间层执行一次,而不是让客户端执行N次。此外,这使您的代码更少依赖数据库。

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

相比之下,你现在看起来像anemic data model或更糟。

答案 3 :(得分:0)

我不清楚这种情况。

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

如果问题是关于多重继承,那么你就不会有.Net了。

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

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

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