3

我有一个审计属性的抽象基类。为简洁起见说它有一个属性

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

然后我的可审计域对象继承自这个类

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

我有下表 DDL,我想将我的域对象“源”映射到该 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”在“源”类型中没有对应的成员。不支持从上述根类型映射成员。

在我的持久层的上下文中,我不是试图表示继承层次结构,而是在我的应用程序的上下文中,我只是使用一个基类来提供我的所有域对象所需的属性。通过大量摆弄我的映射文件(包括将审计列映射到基本 AbstractAuditableEntity 类型)和阅读,我无法实现我认为非常简单的 ORM 任务。

任何想法或建议都将受到欢迎!谢谢

4

2 回答 2

6

我猜您正在尝试模拟 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

我在 Models 命名空间中实现了一个接口,如下所示:

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

然后扩展了具有这些字段的数据实体的部分类:

public partial class DataModelIWantToAudit : IAuditable
{
}

然后用 Linq 的魔力覆盖SubmitChangesDataContext检查接口的实现OfType<>

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);
}

希望有帮助!-凯利

于 2009-08-28T00:18:50.640 回答
2

Kelly 展示了如何做到这一点的一个很好的示例——但是您基本上已经遇到了 Linq-to-SQL 的限制之一。

如果您的数据库表或多或少 1:1 映射到您的域对象,它会非常有用。但它很弱,一旦不再是这种情况,就会导致大量额外的工作。

在这种情况下,只要您有域对象继承和其他需要映射到数据库表的东西,最好的办法就是改用 ADO.NET Entity Framework。EF 是专门为处理这些事情而设计的——如果你曾经认为“我需要映射我的对象......”那么你应该认为 EF!:-)

诚然,当前在 .NET 3.5 SP1 中发布的 EF 有其缺陷和烦恼,但是作为 .NET 4.0 浪潮的一部分(应该在 2009 年年底之前发布)的 EF 4 应该可以解决很多问题疣!

查看ADO.NET Entity Framework 团队博客,了解 EF4 将为我们带来什么!

马克

于 2009-08-28T06:02:56.233 回答