1

私は現在、Web サービスを使用していくつかの API を公開しているデータ アクセス レイヤーを持っています。

API 呼び出し

[WebMethod]
public List<GlobalStat> GetStats()
{
    List<GlobalStat> Stats = new List<GlobalStat>();

    string sql = @"
       A huge multi-line SQL query
    ";

    try
    {
        string ConString = Constants.connString;
        con = new SqlConnection(ConString);

        cmd = new SqlCommand(sql, con);
        con.Open();
        dr = cmd.ExecuteReader();

        while (dr.Read())
        {
            GlobalStat stat = new GlobalStat();
            stat.Key = dr[0].ToString();
            stat.Value = int.Parse(dr[1].ToString());

            Stats.Add(stat);
        }

    }
    catch (Exception x)
    {

        Response.Write(x);
    }

    return Stats;
}

SQLの書き方が少し気になります。

これには、データベース名、テーブル名など、非常に多くのものがハードコーディングされています。

この問題を解決するには、すべての SQL コマンドを 1 か所にまとめた別のグローバル ファイルを作成するだけですか、それともより良いパラダイムがありますか? アプリケーション内で SQL テーブルを作成していませんが、これらのテーブルは別の構築済みデータベースに存在します。

インライン SQL を使用してデータベースからデータを生成するアプリケーションをどのように構築すればよいですか?

4

3 に答える 3

5

適切な方法は、私見ですが、ストアドプロシージャを呼び出すことです。C# コードでは、ストアド プロシージャを参照し、適切に型指定されたパラメーターを渡すだけです。C# コードに組み込まれたアドホック SQL は、多くのことへの扉を開きます。そのうちの少なくとも 1 つは、SQL インジェクションとプラン キャッシュの非効率的な使用です。さらに、アプリケーションを再コンパイルおよび再デプロイせずにクエリをリファクタリングすることは非常に困難です。これは、一部の変更 (ストアド プロシージャへのインターフェイスが変更されたときなど) には必要ですが、他の多くの典型的なクエリの変更には必要ありません。

于 2012-06-13T01:11:22.057 に答える
4

あなたはいくつかの問題を提起し、あなたが示しているコードはさらにいくつかの問題を提起しています。あなたが考えたいかもしれないこと:

  • データベース中心のアクティビティを独自のクラスに制限するようにしてください。GlobalStatsオブジェクトの行のリストを返す方法については、データベースからそのデータを引き出して実際のオブジェクトにする処理を行う実際のクラスを除いて、誰も知る必要はありません。誰も。他の誰かが知っている場合、あなたのクラスは情報隠蔽を使用していません (私たちはオブジェクト指向言語を使用しているため、使用する必要があります)。

  • オブジェクトが を実装している場合はIDisposabletry {} finally {}ブロックでラップするか、usingステートメントでラップする必要があります (以下の 2 番目の例を参照)。

  • 接続文字列は、実際にそれを必要とするクラスにのみアクセスできるようにする必要があります (懸念事項の分離の一部)。おそらく、その情報を持つ基本 DataAccess クラスを持っていますか?

    public abstract class DataAccess 
    {
        protected const string ConnectionString = "YourConnectionStringHere";
    }
    

その後、リポジトリはこのクラスから継承でき、コードが不必要に結合される原因となるグローバルな静的定数はありません。

あなたが書いているものを私が書く方法は次のとおりです(注意してください、このコードは実際に使用することを意図したものではなく、説明のみを目的としています):

[WebMethod]
public List<GlobalStat> GetStats()
{
    GlobalStatsRepository repository = new GlobalStatsRepository();
    List<GlobalStat> stats = repository.GetStats();
    return stats;
}

データ アクセス層

public class GlobalStatsRepository
{
    public List<GlobalStat> GetStats()
    {

         string sql = @"SELECT * from GlobalStats"; //no, not a good practice

        var stats = new List<GlobalStat>();

        try
        {
            string ConString = Constants.connString;
            conn = new SqlConnection(ConString);

            cmd = new SqlCommand(sql, conn);
            conn.Open();
            dr = cmd.ExecuteReader();

            while (dr.Read())
            {
                GlobalStat stat = new GlobalStat();
                stat.Key = dr[0].ToString();
                stat.Value = int.Parse(dr[1].ToString());

                stats.Add(stat);
            }

        }
        catch (SQLDataReaderException ex)
        {
            logger.Log(ex);
            throw;
        }
    return stats;
    }
}

パラメータ化されたクエリの例

public List<GlobalStat> GetStatsById(int id)
{
    var stats = new List<GlobalStat>();

    string sql = @"SELECT * from GlobalStats WHERE Id = @Id";
    using (SqlConnection conn = new SqlConnection(ConString))
    {
         conn.Open();
         using (SQLCommand command = new SqlCommand(sql, conn))
         {         
             command.Parameters.Add(new SqlParameter("Id", id));
             SqlDataReader reader = command.ExecuteReader();
             while (reader.Read())
             {
                  GlobalStat stat = new GlobalStat();
                  stat.Key = dr[0].ToString();
                  stat.Value = int.Parse(dr[1].ToString());

                  stats.Add(stat);
             }
         }
     }
     return stats;
}
于 2012-06-13T01:17:09.417 に答える
2

ストアド プロシージャまたはLINQ to SQLは、C# 内でよく使用される 2 つのデータベース アクセス パラダイムです。

LINQ to SQL の詳細については、Scott Gu のブログのUsing Linq to SQLを参照してください。

于 2012-06-13T01:17:01.583 に答える