【问题标题】:Mapping a derived class to a table in Linq-to-SQL将派生类映射到 Linq-to-SQL 中的表
【发布时间】:2010-11-23 13:49:24
【问题描述】:

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

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 任务。

欢迎提出任何想法或建议! 谢谢

【问题讨论】:

    标签: linq-to-sql inheritance orm mapping derived-class


    【解决方案1】:

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

    然后在DataContext 上覆盖SubmitChanges 以使用Linq OfType&lt;&gt; 的魔力检查接口的实现:

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

    希望对您有所帮助! -凯莉

    【讨论】:

      【解决方案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 team blog 了解 EF4 将为我们带来什么的预告片!

      马克

      【讨论】:

      • 我仍然为无法轻松地将简单的派生类映射到假定的“ORM”中的表而感到震惊;-)。我所需要的只是确认我无法实现这一点……您现在已经提供了。谢谢。还要感谢 Kelly,因为您提供的解决方案是我最终想要实现的,但是在 Linq-to-SQL 的上下文中,在基类中实现 IAuditable 属性是不可能的
      猜你喜欢
      • 2010-11-26
      • 2016-10-03
      • 1970-01-01
      • 2012-02-15
      • 2019-03-03
      • 2023-04-02
      • 2023-03-14
      • 1970-01-01
      • 2010-12-28
      相关资源
      最近更新 更多