3

監査プロパティの抽象基本クラスがあります。簡潔にするために、1 つのプロパティがあるとします。

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 タスクと認識しているものを達成できません。

どんな考えや提案も大歓迎です!ありがとう

4

2 に答える 2

6

updated_onRuby on Railsのような監査フィールドをエミュレートしようとしていると思いますcreated_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
{
}

そして、 LinqSubmitChangesDataContextマジックを使用してインターフェイスの実装を確認するために をオーバーライドし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: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 に答える