No puedo entender por qué el valor HasChanged
de mi objeto SqlCacheDependency
regresa originalmente de la ejecución del comando como falso, pero en algún lugar casi inmediatamente después de que vuelve de la base de datos, el valor cambia a verdadero.¿Por qué mi SqlCacheDependency HasChanged vuelve falso pero casi inmediatamente después de los cambios en verdadero?
A veces esto sucede incluso antes de que el elemento se inserte en la memoria caché, haciendo que la memoria caché lo descarte inmediatamente, a veces después de la inserción, y puedo tomar un enumerador que ve la clave en la memoria caché pero incluso antes de ese artículo en la memoria caché ha sido eliminado.
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
La base de datos es MS SQL Server 2008, Service Broker está habilitado, y algunos de salida hace caché y permanecerá en caché. Por ejemplo, éste funciona bien:
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
El código que llama al procedimiento almacenado en cuestión que falla:
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;
código que funciona
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;
está sobrecargado El método AddToCache
y tiene más pruebas en él; El _cache.Insert
directo en el método de trabajo es eludir esas otras pruebas. El código de trabajo ayuda a determinar si el almacenamiento en ca ocurre en absoluto.
Se puede ver que cuando los datos "no trabajo" se recupera en un principio, todo está bien:
Pero en algún lugar al azar allá de ese punto, en este caso, simplemente entrar en el siguiente método
Y sin embargo, los datos no cambia en absoluto; Soy el único que toca esta instancia de la base de datos.
Lo intentaré, pero creo que es poco probable, porque el param hash solo se usa para construir el nombre de la clave bajo la cual se crea el elemento de caché. –
@TheEvilGreebo: Lo siento, no creo que me haya comunicado lo suficientemente bien. Creo que el problema es esta línea de código 'new SqlParameter (" @ ER_ID ", _eR_ID)'. Esto pasa todo el objeto _eR_ID al parámetro y no estoy seguro exactamente cómo lo traduce a un valor para Sql (sospecho que llama a ToString() en el objeto). Anteriormente utilicé _eR_ID.Value, por lo que creo que el cambio mínimo que necesita es 'new SqlParameter (" @ ER_ID ", _eR_ID.Value)'. –
Oh, ya veo lo que quieres decir. Bueno, _eR_ID es un SqlInt32, así que uno pensaría que inicializar un nuevo SqlParm usando eso no causaría problemas, ¡pero vale la pena intentarlo! –