2

次のように C# で表された SQL のテーブルがあるとします。

public class Product
{
   public int ID { get; set; }
   public string Name { get; set; }
   public string Picture { get; set; } // filename of the picture, e.g. apple.jpg
   public int CategoryID { get; set; }
}

次に、データベースにクエリを実行してオブジェクトを取得します。たとえば、次のような値を使用します。

ID = 1
Name = Yellow apple
Picture = apple.jpg
CategoryID = 25

すべて完全に正常です。現時点で私が考えていることは次のとおりです。製品を表示したい場合、画像への正確なファイルパスなど、データベースからクエリされていない追加情報が必要です。

りんご.jpg

、しかし、おそらく次のようなものが必要です

〜/images/apple.jpg


そこで、以下の3つの可能性を考えました。

1.) 新しいプロパティをクラス Product に追加します

public string PictureUrl
{
    get
    {
        return "~/images/apple.jpg";
    }
}

2.) プレゼンテーション ロジックの実行中に完全な URL を指定します。

public void ShowProductDetails()
{
    Product p = ProductRepo.GetProduct(id);

    txtName.Text = p.Name;
    imgPicture.ImageUrl = "~/images/" + p.Picture;
}

3.) デコレータ パターンを使用する

最初のアプローチは (かなり長い間使用してきましたが) 私には間違っているように思えます。これをハードコーディングするのが良い方法かどうかはわかりません。

2 番目のアプローチの方が優れていますが、簡単に再利用できないという意味では悪い方法です。同じことをしている場所が複数あり、何かが変わった場合...パスを保持する静的定数を指定するとうまくいくかもしれません...

3 番目の可能性は、保守性の点で非常に複雑に思えます。私のクラスの数は、おそらく倍増する必要があります。今30のクラスがあるとしたら、突然60になります:/

このようなことを行うための最良/推奨の方法は何ですか? db スキーマに含まれていないプロパティを POCO に追加すると、Dapper.Contrib や Rainbow などのライブラリを使用できなくなります。消去"。すべてのコマンドに対して SQL 文字列をハードコーディングする必要がありますが、これは、同じことを常に行っていると、しばらくすると非常に面倒になります。

編集:

Govind KamalaPrakash Malviya のソリューションは素晴らしいですが、毎回使用できるわけではありません。アルバムの写真の数など、より複雑なものであっても、あらゆるタイプのプロパティについてこれを解決する方法が必要です。アルバムと一緒に写真の数を照会するのは良い考えですが、何に割り当てますか? Decorator パターンを使用して装飾されたクラスを作成しますか?

この種のアーキテクチャの問題をどのように解決しますか?

4

2 に答える 2

4

プレゼンテーション層のみの画像パスなので、プレゼンテーション層で操作する必要があると思います。3番目のものを使用しますが、ユーティリティメソッドを使用して簡単にします

public class PathUtility
{
    public static string ImageUrl(string imageName)
    {

          if(string.IsNullOrEmpty(imageName))
          {
               throw new Exception("Image name not valid!!");
          } 
          else
          {
               return "YourImageDirectroyUrl" + imageName;
          }

    } 
}

簡単に使用できます

PathUtility.ImageUrl("apple.jpg");
于 2012-06-30T15:44:40.480 に答える
1

私は通常、エンティティ オブジェクトをそのままにして、対応するエンティティへの参照を保持するか、エンティティ オブジェクト自体から対応するプロパティを実装する追加のデータ コンテナーを作成することで、これを解決します。後者の場合、マッピング ライブラリ ( AutoMapper ) を使用して、エンティティから拡張コンテナーにデータをコピーします。

追加のプロパティを埋めるためのロジックは、通常、ファクトリ (またはファクトリ メソッド) にあります。これをアーキテクチャのどこに配置するかは、あなた次第です。現在のプロジェクトでは、クライアント側のデータ アクセス ファサードにそれらを含めています。これは、あまりにも多くの DTO でデータ アクセス レイヤーを混乱させたくないためです。これはもちろん、データ アクセス層が追加のプロパティの取得をサポートする必要があることを意味します。あなたの場合、のような操作ですint GetNumberOfPhotosForAlbum(Album album)

データ アクセス レイヤーのコントラクトが増え続けることによるリスクよりもメリットの方が大きいことがわかりました。当然のことながら、上記の例のように、単にEnhancedAlbum GetEnhancedAlbumWithAllKindsOfExtraProperties(long albumId). これは、サービス呼び出しの頻度の増加によるオーバーヘッドのため、一部のシナリオではパフォーマンスの問題になる可能性もあります。最終的には、プロジェクトに最適なものを決定する必要があります。

Albumエンティティ ( ) は変更されず、永続性、クライアント ロジック、およびマッピングの間の関心事項が明確に分離されているため、このアプローチが気に入っています。

例:

class Album
{
    string Name { get; set; }
}

class EnhancedAlbum
{
    Album Album { get; set; }
    int NumberOfPhotos { get; set; }
}

class EnhancedAlbumFactory
{
    private MyDataService _dataService;

    //include some means of constructing or (better) injecting the data service

    EnhancedAlbum GetEnhancedAlbum(Album album)
    {
        return new EnhancedAlbum
               {
                   Album = Album,
                   NumberOfPhotos = _dataService.GetNumberOfPhotosForAlbum(album);
               };
    }
}
于 2012-07-01T14:42:04.120 に答える