2

クラスのプライベートメソッドを書いています。これにパラメーターとして、SQLServer2008テーブルの行のIDを表す整数のリストを渡します。

渡された整数の1つが。に等しいすべての行で(列)List<string>のaを返したいと思います。だから私が渡すと。"Name""ID"List<int> {1, 2, 3 }

基本的にコマンドを実行したい(SELECT Name FROM Table WHERE ID = 1 OR ID = 2 OR ID = 3).ToList<string>()

私が使用しているデータベースは非常に混雑しているため、ソリューションを可能な限り最適化することが非常に重要です。これを念頭に置いて、.dbmlファイルを使用してこのDBへのリンクを作成し、Linq to SQLを使用してデータベースにクエリを実行する方がよいかどうか疑問に思っていますか?

または、単にSQLCommandオブジェクトを作成し、それを1回実行し、リーダーを反復処理してリストに保存しますか?これを行うための最適な方法は何ですか?非常にビジーなデータベースを表すために.dbmlファイルを作成することは悪い習慣ですか?

4

5 に答える 5

5

.dbmlの作成は、サーバー側のパフォーマンスとはほとんど関係がありません。これにより、呼び出し側のツールが変更されますが、サーバーは、.dbmlからのコマンドと手動でコーディングされたコマンドの違いに実際には気づきません。少なくとも、これほど単純なものではありません(複雑なクエリの場合、手動でコーディングされていることに注意してください)。多くの場合、クエリはマシンで生成されたクエリよりもパフォーマンスが優れている可能性があります)。

発信者のパフォーマンスに関して。.dbmlは、通常のすべてのコマンド/リーダーなどの単なるラッパーです。これにより、処理を高速化することはできません。場合によっては、式を適切に解析できない場合や、解析された結果をキャッシュしない場合(TSQLの観点から)、処理速度が低下する可能性があります。

ただし、私が言うことは、 dapperがこれを非常にうまく処理するということです。

var ids = new List<int>{1,2,3};
var names = conn.Select<string>("select Name from Table where ID in @ids",
      new {ids}).ToList();

dapperはin @ids使用法を特定し、それをパラメーターとして展開して、以下を実行します。

select Name from Table where ID in (@p__0, @p__1, @p__2)

(またはそのようなもの)-1、2、および3をそれらの値として渡します。

それはあなたに与えます:

  • 発信者の利便性
  • 発信者のパフォーマンス(dapperは大幅に最適化されています)
  • 完全なパラメータ化
    • サーバーでの最適なクエリプランの再利用を可能にする

より一般的には、dapperは一般的なエンティティマッピングも適切に処理します。次に例を示します。

int id = 12345;
var customer = conn.Select<Customer>("select * from Custom where Id = @id",
    new { id }).Single();
于 2012-07-26T09:43:56.553 に答える
2

私がするいくつかのこと:

A.テーブル値パラメーターを使用する

CREATE TYPE LocationTableType AS TABLE 
( ID INT);
GO

B.ストアドプロシージャを使用する(TVPで)

CREATE PROCEDURE dbo. usp_GetLocationNames
    @TVP LocationTableType READONLY
    AS 
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

    SELECT Name
    FROM dbo.Location l
    JOIN @TVP t ON l.ID = t.ID

C.ダーティ読み取りを許可する-トランザクション分離レベルの読み取りをコミットしないように設定します。

D.行をカウントしない-SETNOCOUNTON;

E.結果セットを一定期間キャッシュします

私はあなたのアプリケーションやあなたの状況についてほとんど知らないので、これらの項目は「一般的に」私がほとんどのprocで行うことです。明らかに、現金を分配する前に誰かの銀行口座の残高をチェックしていた場合、ダーティリードを許可したり、結果セットをキャッシュしたりすることはできません。しかし、ほとんどの場合、これらのことは許容されます。

于 2012-07-26T09:50:06.117 に答える
0

トラフィックを制限するには、データベースへのラウンドトリップの数を減らす方がよいため、コマンドを1つだけ発行する場合は、クエリを複数またはパラメーター化する代わりにIN句を使用することもできます。

于 2012-07-26T09:31:21.593 に答える
0

数値IDで選択する場合は、WHERE句を動的に作成しても安全です(つまり、WHERE ID IN(1,2,3、...)

より高度な方法は、XMLパラメーターを使用してSPを作成することです。サンプルコードスニペット:

DECLARE @xmlIds AS XML
SET @xmlIds = '<Ids><ID>1</ID><ID>2</ID></Ids>'

SELECT Name FROM Table
WHERE ID IN (
    SELECT
        Data.row.value('.', 'INT')
        FROM
        @XmlIds.nodes('/Ids/ID') As Data(row))
于 2012-07-26T09:50:11.210 に答える
0

これらはすべて、ネイティブC#とSQL 2008を使用してネイティブに実行できます。SQL2008では、ユーザー定義のテーブルタイプ、およびストアドプロシージャのテーブル値パラメーターが導入されました。

したがって、以下はあなたが望むものを正確に与えるでしょう、

CREATE TYPE UdtId AS TABLE
(
    [ID] INT NOT NULL
    PRIMARY KEY NONCLUSTERED ([ID] ASC)
)

CREATE PROCEDURE spGetCustomerByIds
    @IDS UdtId READONLY
AS
BEGIN
    SELECT
        C.*
    FROM Customer C
    INNER JOIN UdtId I ON
        C.ID = I.ID
END

うまくいけば、その背後にあるC#コードは明らかですが、次のようになります。

public foo GetCustomerDataByIds(IEnumerable<int> ids)
{
    using (var command = new SqlCommand())
    using (var adatper = new SqlAdapter())
    using (var dataSet = new DataSet())
    {
        command.Text = "spGetCustomerByIds";
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.AddWithValue("@IDS", GetDataTableOfIds(ids));
        // execute and return the stuff you're after
    }
}

private DataTable GetDataTableOfIds(IEnumerable<int> ids)
{
    var table = new DataTable();
    table.Columns.Add(new DataColumns("ID", typeof(int));
    foreach (var id in ids)
    {
        table.Rows.Add(id);
    }
    return table;
}
于 2012-07-26T09:53:56.527 に答える