C#データベースアクセス、Dapper、SQL、POCO - プログラミング設計

asp.net dapper design-patterns oop sql

質問

私はこれがかなり基本的なものだと知っていますが、私と一緒に裸にしてください。ここではかなり暑いです(今の35℃)ので、私の脳はおそらく融解段階にあります。

長い話を簡単に言えば、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

すべて正常に正常です。現時点で私が瞑想しているのは、製品を見せたいと思ったら、正確なファイルパスをイメージしたような、データベースから照会されなかった追加情報が必要です。

apple.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.)デコレータパターンを使用する

私はレイヤードWebアプリケーションを作成しようとしているので、最初のアプローチは私には間違っているようです(かなり長い間使っていますが)。私はこれをハードコーディングすることが良い方法であるかどうかは分かりません。

2番目のアプローチは良いですが、それは簡単に再利用することはできません。私が同じことをして何かを変えている場所が複数ある場合は...パスを保持する静的定数を指定するとうまくいくかもしれません...

第3の可能性は、保守性という点ではかなり複雑に思えます。私のクラスの数はおそらく倍増しなければならないでしょう。私が30のクラスを今持っているなら、それは突然60になるだろう:

このようなことをするための最良の/推奨される方法は何ですか? dbスキーマに含まれていないPOCOにプロパティを追加すると、Dapper.ContribやRainbowなどのライブラリを使用できません。なぜなら、「選択」してもうまく動作しても、削除する。私はいつも同じことをやっているとき、いくつかの時間の後に本当に退屈になるすべてのコマンドのSQL文字列をハードコードする必要があります。

編集:

OK、もっと具体的にすべきだったのかもしれません... Govind KamalaPrakash Malviyaのソリューションは素晴らしいですが、毎回使うことはできません。どのような種類のプロパティ、さらに複雑なものであっても、たとえばアルバムの写真数など、この問題を解決する方法が必要です。アルバムと一緒に写真の数を問い合わせるのは良い考えですが、それを何に割り当てるか?デコレータパターンを使用して装飾クラスを作成しますか?

このようなアーキテクチャの問題をどうやって解決しますか?

受け入れられた回答

私は通常、エンティティオブジェクトをそのまま残して、対応するエンティティへの参照を保持するか、またはエンティティオブジェクト自体から対応するプロパティを実装する余分なデータコンテナを作成することでこれを解決します。後者の場合、マッピングライブラリ( 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);
               };
    }
}

人気のある回答

私はプレゼンテーションレイヤーのためのイメージパスだからプレゼンテーションレイヤーでそれを操作する必要があると思います。それで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");


ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ