将派生类映射到 Linq-to-SQL 中的表

发布于 2024-08-03 03:06:14 字数 1401 浏览 10 评论 0原文

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

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

任何想法或建议将非常受欢迎! 谢谢

I have an abstract base class for audit properties. For brevity say it has one property

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

And then my auditable domain objects inherit from this class

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

I have the following table DDL to which I want to map my domain object "Source". Essentially the relationship between each (concrete) domain object and table is 1-1, with each table having the required audit column.

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

Using an external mapping file my first attempt to map the class to the table would foolishly be:

<?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>

However this generates the following exception:

The column or association 'CreatedTime' in the mapping had no corresponding member in type 'Source'. Mapping members from above root type is not supported.

Within the context of my persistence layer I am not trying to represent an inheritance hierarchy as such, but within the context of my application I am simply using a base class to provided properties required by all my domain objects. With a lot of fiddling with my mapping file (including mapping the audit columns to the base AbstractAuditableEntity type) and reading around, I am unable to achieve what I perceive as quite a straighforward ORM task.

Any thoughts or suggestions would be most welcome!
Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

带上头具痛哭 2024-08-10 03:06:14

我猜测您正在尝试模拟审核字段,例如 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<> 魔力的界面:

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

希望有帮助!
-凯利

I'm guessing that you are trying to emulate auditing fields like Ruby on Rails updated_on, created_on. If so, here is how I accomplished something similar using this post as a starting point
http://weblogs.asp.net/stevesheldon/archive/2008/02/23/a-method-to-handle-audit-fields-using-linq-to-sql.aspx

I implemented an interface in the Models namespace like so:

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

And then extended the partial classes of the data entities that had these fields:

public partial class DataModelIWantToAudit : IAuditable
{
}

And then overrode SubmitChanges on the DataContext to check for the implementation of the interface with the magic of Linq 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);
}

Hope that helps!
-Kelly

玩物 2024-08-10 03:06:14

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

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

在这种情况下,一旦您拥有域对象继承和其他需要映射到数据库表的内容,您最好的选择就是查看 ADO.NET 实体框架。 EF 是专门为处理这些事情而设计的 - 如果您曾经想过“我需要映射我的对象......”那么您应该考虑 EF! :-)

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

查看 ADO .NET 实体框架团队博客,了解 EF4 将为我们带来的一些预告!

马克

Kelly showed a great sample of how to do it - but you've basically hit one of the limitations of Linq-to-SQL.

It works great if you database table map more or less 1:1 to your domain objects. But it's weak and causes a lot of extra work once this is no longer the case.

In such a case, as soon as you have domain object inheritance and other things that need to be mapped to database tables, you're best bet would be to check out ADO.NET Entity Framework instead. The EF is specifically designed to handle these things - if you ever think "I need to map my objects ......" then you should think EF! :-)

Granted, the current EF shipping in .NET 3.5 SP1 has its warts and annoyances, but the EF 4 that is part of the .NET 4.0 wave (which should ship before the end of this year 2009), should solve a great many of those warts!

Check out the ADO.NET Entity Framework team blog for some teasers of what EF4 will bring us all!

Marc

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文