2017-12-13 48 views
1

私はかなり大きなアプリケーションで、階層化されたアーキテクチャパターンに従おうとしています。 DBALでは、私は流暢に構成されたNHibernateを使用します。データベースオブジェクトは時々このような関連を持って次のようにNHibernateを使ってエンティティの関連オブジェクトを持続させる戦略

public class HeaderDbo 
{ 
    public HeaderDbo() 
    { 
     Details = new List<DetailDbo>(); 
    } 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual IList<DetailDbo> Details { get; set; } 
} 

public class DetailDbo 
{ 
    public virtual int Id { get; set; } 
    public virtual string DetailName { get; set; } 
    public virtual HeaderDbo Header { get; set; } 
    public virtual RelevantObjectDbo RelevantObject { get; set; } 
} 

public class RelevantObjectDbo 
{ 
    public virtual int Id { get; set; } 
    public virtual string RelevantText { get; set; } 
} 

マッピングは次のとおりです。

public class HeaderDboMap : ClassMap<HeaderDbo> 
{ 
    public HeaderDboMap() 
    { 
     Table("Header"); 
     Id(x => x.Id).Column("Id"); 
     Map(x => x.Name); 
     HasMany(x => x.Details) 
      .Inverse() 
      .Cascade.All(); 
    } 
} 

public class DetailDboMap : ClassMap<DetailDbo> 
{ 
    public DetailDboMap() 
    { 
     Id(x => x.Id).Column("Id"); 
     Table("Detail"); 
     Map(x => x.DetailName); 
     References(x => x.Header).Column("HeaderId"); 
     References(x => x.RelevantObject).Column("RelevantObjectId") 
      .Cascade.SaveUpdate(); //?? 
    } 
} 

public class RelevantObjectDboMap : ClassMap<RelevantObjectDbo> 
{ 
    public RelevantObjectDboMap() 
    { 
     Id(x => x.Id).Column("Id"); 
     Table("RelevantObject"); 
     Map(x => x.RelevantText); 
    } 
} 

を今、DBOSは必ずしもデータベース構造を反映していないためにどのマップされているアプリケーションドメインエンティティがありますワン1対1。たとえば、ヘッダーはヘッダーのままですが、DetailはDetailDboとRelevantObjectDboの部分から形成されます。次に、アプリケーションはエンティティ上でそのことを行います。詳細の一部の変換が行われますが、これを永続化する必要があります。

ディテールエンティティのうちディテールテーブルに移動する必要がある部分のみに影響を与え、RelevantObjectテーブルには何も影響しないものとします。モデルについて考えるのは間違った方法かもしれませんが、永続的な作業の仕方についても実践する必要があります。ですから、私はNHibernateにRelevantObjectテーブル上の何も触れずにDetailテーブルを更新させたいだけです。これはまさに質問です。実際にはどうすれば実現できますか?

もちろん、DBモデルははるかに大きく複雑であり、アプリケーションロジックもそうです。 DBの部分がDBから完全に読み込まれても、すべてのデータがアプリケーションモデルに反映されるわけではありませんが、データのRelevantObject部分を処理しないBLの部分がある可能性があります。しかし、データをデータベースに保存し直すためには、DBモデルを完全に水分補給する必要があり、必ずしも実用的ではないようです。ですから、どのようにしてNHibernateにRelevantObjectに「触れないように」指示することができますか?言い換えれば、dbo.Detail.RelevantObjectIdを更新しないでください。

DetailDbo.RelevantObjectプロパティに異なるカスケードオプションを適用しようとしましたが、nullにとどまっていると、NHibernateは常にRelevantObjectIdをNULLに設定したいと思います。

すべての関連付けを介してデータベースの半分をロードして保存せずに、BLの「パート」に関連するデータに変更を書き込む方法を理解できません。

ありがとうございました!

+0

DetailDbo.RelevantObjectでカスケードをNoneに設定し、正しいIDが設定された「空の」オブジェクトにプロパティを設定すると、更新が希望の方法、つまり参照dboで行われることがわかりました。 Detail.RelevantObjectIdは正しく設定されたままであり、dbo.RelevantObjectはタッチされません。しかし、これはあまりにも不器用です、私は思う - 良い方法はありませんか? –

+0

私が今見ている戦略の1つは、dbの読み込みエンティティとセーブの両方を担当するリポジトリでは、最初にDBOを読み込み、リポジトリが「必要な」範囲内でそのオブジェクトをエンティティから更新して保存するバック。また、不器用ですが、 "持続するもの"のロジックがDBAL内に含まれているため、アプローチが気に入っています。これは、エンティティが永続性の詳細を知らないためです。これをいくつかの経済的な方法で実装しようとしています... –

答えて

0

これらのアップデートはどのように行っていますか? RelevantObjectで何も修正していない場合、NHibernateはそのテーブルの更新を送信しません。たとえば:

var header = session.Get<HeaderDbo>(1); 
header.Details.First().DetailName = "Whatever"; 
session.Flush(); 

は更新がRelevantObjectテーブルに発行するべきではありません。

+0

それは本当です。しかし、問題は、時にはDBOのカーボンコピーではないエンティティを保持する必要があることです。たとえば、HeaderDbo、DetailDbo、RelevantObjectDbo(データベーステーブルの反映)ではなく、BusinessEntityオブジェクトを処理します。また、このエンティティはdbo.Headerテーブルとdbo.Detailテーブルに永続化する必要があるため、HeaderDboとDetailDboを使用してこの「保存」を実行するのは当然ですが、DBOの全体の配列を再作成するための十分な情報はBusinessEntityにありません。紛争。 –

+0

私は完全に従うか分からない。 BusinessEntityの情報から取得できるエンティティを取得し、それらのエンティティのみを更新しますか?いくつかのプロパティを値に更新しても、それは正常です。私は、理解するためにあなたの状況のより完全な例が必要だと思います。とにかく、列レベルの更新を避けると、 "DynamicUpdate();"を使うことができますNHのマッピングでは、エンティティの変更された列に対してのみ更新を発行します。 –

+0

正当な戦略は、DBOをデータベースからロードして、BusinessEntityから更新することです - 特定のビジネス操作に必要な方法ですか?これは私が最後にやったことのようなもので、実際には解決策が気に入っていました。私がもっと良いものを見逃しているのかどうか疑問に思っていました –

関連する問題