2009-08-27 85 views
3

我有一个用于审计属性的抽象基类。为了简便起见说它有一个属性将派生类映射到Linq-to-SQL中的表格

Public MustInherit Class AbstractAuditableEntity 
    ... 
    Public Property CreatedTime() As DateTimeOffset 
    ... 
End Class 

然后我的审计域对象从该类

Public Class Source 
    Inherits AbstractAuditableEntity 
    ...   
    Public Property SourceId() As String 
    ... 
End Class 

继承我有以下表的DDL到我要地图我的域对象的“源”。实质上,每个(具体)域对象和表之间的关系是1-1,每个表都具有所需的审计列。

CREATE TABLE Source 
( 
    SourceID VARCHAR(10) NOT NULL, 
    CreatedTime DATETIMEOFFSET(3) NOT NULL, 
    CONSTRAINT PK_Source PRIMARY KEY (SourceID)) 
GO 

使用外部映射文件我的第一次尝试来映射类表中会愚蠢是:

<?xml version="1.0" encoding="utf-8"?> 
<Database Name="" xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007"> 
    <Table Name="Source" Member="Sources"> 
    <Type Name ="Source"> 
     <Column Name="SourceID" Member="SourceID" IsPrimaryKey="true" CanBeNull="false"/> 
     <Column Name="CreatedTime" Member="CreatedTime" />  
    </Type> 
    </Table> 
</Database> 

然而,这会产生以下例外:

列或关联“CreatedTime '在映射中没有对应的'Source'类型的成员。 不支持来自以上根类型的映射成员。

在我的持久层的上下文中,我并不试图表示继承层次,而是在我的应用程序的上下文中,我简单地使用基类来提供所有域对象所需的属性。随着我的映射文件(包括将审计列映射到基本的AbstractAuditableEntity类型)和阅读周围的许多摆弄,我无法实现我认为是相当直接的ORM任务。

任何想法或建议将是最受欢迎的! 谢谢

回答

1

Kelly展示了一个很好的例子 - 但你基本上已经碰到了Linq-to-SQL的一个限制。

如果你的数据库表映射或多或少1:1到你的域对象,它会很好用。但是,如果这种情况不再存在,它就会很弱并且会导致很多额外的工作。

在这种情况下,只要您有域对象继承和其他需要映射到数据库表的东西,最好的办法就是查看ADO.NET实体框架。EF是专门设计来处理这些事情的 - 如果你曾经想过“我需要地图我的物体......”那么你应该考虑EF! :-)

当然,.NET 3.5 SP1中的当前EF运输有其瑕疵和烦恼,但是作为.NET 4.0 wave(它应该在2009年年底之前发布)的一部分的EF 4,应该解决很多这些疣!

请查看ADO.NET Entity Framework team blog了解EF4将给我们带来的一切刺激!

马克

+0

我还是不能够很容易地映射在一个所谓的“ORM”派生类到表的简单;-)的冲击下岌岌可危。我所需要的只是确认我无法实现这个目前你已经提供的。谢谢。 感谢凯利也为您提供的解决方案是我最终试图实现的,但是在Linq-to-SQL实现的背景下,不可能在基类中实现IAuditable协议 – 2009-08-28 18:49:14

5

我猜你试图模拟像Ruby on Rails审计字段updated_oncreated_on。如果是这样,这是我如何使用这个职位作为一个起点 http://weblogs.asp.net/stevesheldon/archive/2008/02/23/a-method-to-handle-audit-fields-using-linq-to-sql.aspx

我实现了在型号命名空间中,像这样的接口来实现类似的东西:

public interface IAuditable 
{ 
    DateTime CreatedOn { get; set; } 
    string CreatedBy { get; set; } 
    DateTime? ChangedOn { get; set; } 
    string ChangedBy { get; set; } 
} 

然后扩展的数据部分类这有这些领域的实体:

public partial class DataModelIWantToAudit : IAuditable 
{ 
} 

,然后在DataContext压倒SubmitChanges来检查接口的实现使用LINQ的魔力:

public override void SubmitChanges(ConflictMode failureMode) 
{   
    //Updates 
    foreach (var updatedModel in GetChangeSet().Updates.OfType<IAuditable>()) 
    { 
     updatedModel.ChangedOn = DateTime.Now; 
     updatedModel.ChangedBy = Membership.GetUser().UserName; 
    } 

    //Inserts 
    foreach (var insertedModel in GetChangeSet().Inserts.OfType<IAuditable>()) 
    { 
     insertedModel.CreatedOn = DateTime.Now; 
     insertedModel.CreatedBy = Membership.GetUser().UserName; 
    } 

    base.SubmitChanges(failureMode); 
} 

希望帮助! -Kelly