12

HasChangedオブジェクトの値がコマンドの実行から最初に false として返される理由がわかりませんSqlCacheDependencyが、データベースから返された直後のどこかで、値が true に変わります。

アイテムがキャッシュに挿入される前にこれが発生し、キャッシュがすぐにアイテムを破棄することもあれば、挿入後であることもあります。キャッシュ内のキーを参照する列挙子を取得できますが、そのアイテムにループする前です。キャッシュは削除されました。

SPROC:

ALTER PROCEDURE [dbo].[ntz_dal_ER_X_Note_SelectAllWER_ID]
        @ER_ID int
AS
BEGIN
    SELECT
        ER_X_Note_ID,
        ER_ID,
        Note_ID
    FROM dbo.ER_X_Note e
    WHERE
        ER_ID = @ER_ID
END

データベースは MS SQL Server 2008 で、ブローカー サービスが有効で、一部の出力がキャッシュされ、キャッシュされたままになります。たとえば、これは問題なく機能します。

ALTER PROC [dbo].[ntz_dal_GetCacheControllerByEntityName] (
    @Name varchar(50)
) AS
BEGIN
    SELECT 
        CacheController_ID,
        EntityName,
        CacheEnabled,
        Expiration
    From dbo.CacheController cc
    WHERE   EntityName = @Name
END

失敗した問題の SPROC を呼び出すコード:

    DataSet toReturn;
    Hashtable paramHash = new Hashtable();
    paramHash.Add("ER_ID", _eR_ID.IsNull ? null : _eR_ID.Value.ToString());
    string cacheName = BuildCacheString("ntz_dal_ER_X_Note_SelectAllWER_ID", paramHash);
    toReturn = (DataSet)GetFromCache(cacheName);
    if (toReturn == null)
    {

        // Set up parameters (1 input and 0 output)
        SqlParameter[] arParms = {
                new SqlParameter("@ER_ID", _eR_ID),
            };
        SqlCacheDependency scd;

        // Execute query.
        toReturn = _dbTransaction != null 
            ? _dbConnection.ExecuteDataset(_dbTransaction, "dbo.[ntz_dal_ER_X_Note_SelectAllWER_ID]", out scd, arParms) 
            : _dbConnection.ExecuteDataset("dbo.[ntz_dal_ER_X_Note_SelectAllWER_ID]", out scd, arParms);

        AddToCache(cacheName, toReturn, scd);
    }

    return toReturn;

動作するコード

        const string sprocName = "ntz_dal_GetCacheControllerByEntityName";
        string cacheControlPrefix = "CacheController_" + CachePrefix;
        CacheControl controller = (CacheControl)_cache[cacheControlPrefix];
        if (controller == null)
        {
            try
            {
                SqlParameter[] arParms = {
                                             new SqlParameter("@Name", CachePrefix),
                                         };
                SqlCacheDependency sqlCacheDependency;

                // Execute query.
                DataSet result = _dbTransaction != null
                                     ? _dbConnection.ExecuteDataset(_dbTransaction, sprocName, out sqlCacheDependency, arParms)
                                     : _dbConnection.ExecuteDataset(sprocName, out sqlCacheDependency, arParms);

                controller = result.Tables[0].Rows.Count == 0
                                 ? new CacheControl(false)
                                 : new CacheControl(result.Tables[0].Rows[0]);

                _cache.Insert(cacheControlPrefix, controller, sqlCacheDependency);
            }
            catch (Exception ex)
            {
                // if sproc retreival fails cache the result of false so we don't keep trying
                // this is the only case where it can be added with no expiration date
                controller = new CacheControl(false);

                // direct cache insert, no dependency, no expiration, never try again for this entity
                if (HttpContext.Current != null && UseCaching && _cache != null) _cache.Insert(cacheControlPrefix, controller);
            }
        }
        return controller;

メソッドがオーバーロードされており、AddToCacheさらに多くのテストが含まれています。作業方法の直接的な_cache.Insert方法は、これらの他のテストをバイパスすることです。作業コードは、db キャッシュが発生するかどうかを判断するのに役立ちます。

「動作していない」データが最初に取得されると、すべて問題ないことがわかります。

ここに画像の説明を入力

しかし、そのポイントを超えたランダムな場所、この例では、次のメソッドにステップインするだけです

ここに画像の説明を入力

それでも、データはまったく変更されていません。データベースのこのインスタンスに触れているのは私だけです。

4

3 に答える 3

6

それは本当に、本当にシンプルで、とてもシンプルで、私はそれを完全に見落としていました.

この記事Creation a Query for Notificationでは、私は何度も精査しましたが、次のように明確に述べています。

SET オプション設定

SELECT ステートメントが通知要求の下で実行される場合、要求を送信する接続には、次のように設定された接続のオプションが必要です。

ANSI_NULLS ON
ANSI_PADDING ON
ANSI_WARNINGS ON
CONCAT_NULL_YIELDS_NULL ON
QUOTED_IDENTIFIER ON
NUMERIC_ROUNDABORT OFF
ARITHABORT ON

さて、私は sproc を読み、読み直し、読み直しましたが、ANSI_NULLS と QUOTED_IDENTIFIER の両方がオンではなく「オフ」であることがわかりませんでした。

私のデータセットは、変更の誤った兆候なしにデータを適切にキャッシュおよび保持するようになりました。

于 2011-12-27T13:47:11.547 に答える
1

問題はあなたのものにあると思います_eR_ID。-1 などの _eR_ID にありえない値を使用する失敗したプロシージャに、ローカル変数を追加してみてください。null が関係している場合に何が起こるかは決して信頼できません。これが問題の原因である可能性があると思います。

試してみることをお勧めする変更されたバージョンは次のとおりです。

DataSet toReturn;
Hashtable paramHash = new Hashtable();

int local_er_ID = eR_ID.IsNull ? -1 : _eR_ID.Value;
paramHash.Add("ER_ID", local_eR_ID.ToString());

string cacheName = BuildCacheString("ntz_dal_ER_X_Note_SelectAllWER_ID", paramHash);
toReturn = (DataSet)GetFromCache(cacheName);
if (toReturn == null)
{

    // Set up parameters (1 input and 0 output)
    SqlParameter[] arParms = {
            new SqlParameter("@ER_ID", local_eR_ID),
        };
    SqlCacheDependency scd;

    // Execute query.
    toReturn = _dbTransaction != null 
        ? _dbConnection.ExecuteDataset(_dbTransaction, "dbo.[ntz_dal_ER_X_Note_SelectAllWER_ID]", out scd, arParms) 
        : _dbConnection.ExecuteDataset("dbo.[ntz_dal_ER_X_Note_SelectAllWER_ID]", out scd, arParms);

    AddToCache(cacheName, toReturn, scd);
}

return toReturn;

重要

上記のコードを作成しているときに、問題の原因を発見したと思います。ストアド プロシージャ パラメータを設定するときは使用して_eR_IDいますが、paramHash を設定するときは を使用してい_eR_ID.Valueます。

コードを書き直すことでこの問題は解決しますが、これが問題の根本にあるのではないかと思います。

于 2011-12-26T22:11:19.287 に答える