SqlDependency 不更新缓存
SqlDependency not updating cache
我正在使用 .NET 4.5、MVC、EF 6 进行项目
我天真地使用 HttpRuntime 缓存实现了一个缓存系统,并且需要在更新该数据时使我缓存的数据无效;除了我忘了考虑我们的生产服务器发布到一组负载平衡的两台服务器...:|
所以在生产环境中,数据更新后,应用程序有时会提供正确的数据,有时会提供旧数据,具体取决于请求到达的服务器。坏消息。
所以我决定定义对 SQL table AcademicTerms 的依赖,这是我的数据来源。但是我做错了什么,我不确定是什么。
SQL 我 运行 在启用 Service Broker 后设置了权限
EXEC sp_addrole 'sql_dependency_role'
GRANT CREATE PROCEDURE to sql_dependency_role
GRANT CREATE QUEUE to sql_dependency_role
GRANT CREATE SERVICE to sql_dependency_role
GRANT REFERENCES on
CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]
to sql_dependency_role
GRANT VIEW DEFINITION TO sql_dependency_role
GRANT SELECT to sql_dependency_role
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO sql_dependency_role
GRANT RECEIVE ON QueryNotificationErrorsQueue TO sql_dependency_role
EXEC sp_addrolemember 'sql_dependency_role', 'MY_ASPNET_APP_USERNAME'
我在获取后插入新数据并因此设置 SqlDependency 的实现(希望不那么天真!):
private void insertIntoCache(
AcademicTermLockingInfo newItem,
string itemKey,
Guid termID) {
var dbContextConnection = db.Database.Connection;
var connectionString = dbContextConnection.ConnectionString;
// important step otherwise it won't work
SqlDependency.Start(connectionString);
CacheItemPolicy policy = new CacheItemPolicy {
AbsoluteExpiration = DateTime.UtcNow.AddMonths(6)
};
CacheItem item = new CacheItem(itemKey, newItem);
using (SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
// command which will be used to notify updates - probably want to parametrize this
using (SqlCommand command =
new SqlCommand(
String.Format("SELECT Name, LockDate FROM dbo.AcademicTerms WHERE ID = '{0}'",
termID),
connection)) {
SqlDependency dependency = new SqlDependency(command);
SqlChangeMonitor monitor = new SqlChangeMonitor(dependency);
policy.ChangeMonitors.Add(monitor);
MemoryCache.Default.Set(item, policy);
// execute once otherwise dependency not registered
command.ExecuteNonQuery();
}
}
}
非常感谢任何帮助!
我做过的事情:
- 在 SQL 服务器中创建了两个新用户,
net
和 sanba
- 将每个 NT* 登录名和 sa 登录名添加到
net
用户,将 net
添加到 sql_dependency_role
- 运行
grant alter on schema::sql_dependency_role to net
和 grant alter on schema::dbo to net
- 检查我的本地 SQL 服务器的
Broker Enabled
选项是否在 Service Broker
下 True
- 尝试交替使用网络缓存和内存缓存(可能不会改变任何东西)
- 尝试使 sql 命令字符串具有完全限定名称
DevUMS.dbo.AcademicTerms
和 dbo.AcademicTerms
- 我查询了
sys.dm_qn_subscriptions
,看到我有一个订阅,很好!
- 我查询了
DevUMS.sys.transmission_queue
发现了一个例外!
An exception occurred while enqueueing a message in the target
queue. Error: 15517, State: 1. Cannot execute as the database
principal because the principal "dbo" does not exist, this type of
principal cannot be impersonated, or you do not have permission.
- 我找到了this SO post with the same error
我缺少的秘诀是 alter authorization on database::DevUMS to [sa];
,我在 the linked SO post's answer 上找到了它。
还有许多其他步骤,例如添加角色以使用适当的登录名,但老实说,我真的不确定这些是否真的有必要。
我将在今天晚些时候发布,然后我将尝试执行最少的步骤并在此处记录。我发现野外的文档非常零散和贫乏,所以我希望这个答案能成为未来参考的明确地方
我正在使用 .NET 4.5、MVC、EF 6 进行项目
我天真地使用 HttpRuntime 缓存实现了一个缓存系统,并且需要在更新该数据时使我缓存的数据无效;除了我忘了考虑我们的生产服务器发布到一组负载平衡的两台服务器...:|
所以在生产环境中,数据更新后,应用程序有时会提供正确的数据,有时会提供旧数据,具体取决于请求到达的服务器。坏消息。
所以我决定定义对 SQL table AcademicTerms 的依赖,这是我的数据来源。但是我做错了什么,我不确定是什么。
SQL 我 运行 在启用 Service Broker 后设置了权限
EXEC sp_addrole 'sql_dependency_role'
GRANT CREATE PROCEDURE to sql_dependency_role
GRANT CREATE QUEUE to sql_dependency_role
GRANT CREATE SERVICE to sql_dependency_role
GRANT REFERENCES on
CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]
to sql_dependency_role
GRANT VIEW DEFINITION TO sql_dependency_role
GRANT SELECT to sql_dependency_role
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO sql_dependency_role
GRANT RECEIVE ON QueryNotificationErrorsQueue TO sql_dependency_role
EXEC sp_addrolemember 'sql_dependency_role', 'MY_ASPNET_APP_USERNAME'
我在获取后插入新数据并因此设置 SqlDependency 的实现(希望不那么天真!):
private void insertIntoCache(
AcademicTermLockingInfo newItem,
string itemKey,
Guid termID) {
var dbContextConnection = db.Database.Connection;
var connectionString = dbContextConnection.ConnectionString;
// important step otherwise it won't work
SqlDependency.Start(connectionString);
CacheItemPolicy policy = new CacheItemPolicy {
AbsoluteExpiration = DateTime.UtcNow.AddMonths(6)
};
CacheItem item = new CacheItem(itemKey, newItem);
using (SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
// command which will be used to notify updates - probably want to parametrize this
using (SqlCommand command =
new SqlCommand(
String.Format("SELECT Name, LockDate FROM dbo.AcademicTerms WHERE ID = '{0}'",
termID),
connection)) {
SqlDependency dependency = new SqlDependency(command);
SqlChangeMonitor monitor = new SqlChangeMonitor(dependency);
policy.ChangeMonitors.Add(monitor);
MemoryCache.Default.Set(item, policy);
// execute once otherwise dependency not registered
command.ExecuteNonQuery();
}
}
}
非常感谢任何帮助!
我做过的事情:
- 在 SQL 服务器中创建了两个新用户,
net
和sanba
- 将每个 NT* 登录名和 sa 登录名添加到
net
用户,将net
添加到sql_dependency_role
- 运行
grant alter on schema::sql_dependency_role to net
和grant alter on schema::dbo to net
- 检查我的本地 SQL 服务器的
Broker Enabled
选项是否在Service Broker
下 - 尝试交替使用网络缓存和内存缓存(可能不会改变任何东西)
- 尝试使 sql 命令字符串具有完全限定名称
DevUMS.dbo.AcademicTerms
和dbo.AcademicTerms
- 我查询了
sys.dm_qn_subscriptions
,看到我有一个订阅,很好! - 我查询了
DevUMS.sys.transmission_queue
发现了一个例外!
An exception occurred while enqueueing a message in the target queue. Error: 15517, State: 1. Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.
- 我找到了this SO post with the same error
True
我缺少的秘诀是 alter authorization on database::DevUMS to [sa];
,我在 the linked SO post's answer 上找到了它。
还有许多其他步骤,例如添加角色以使用适当的登录名,但老实说,我真的不确定这些是否真的有必要。
我将在今天晚些时候发布,然后我将尝试执行最少的步骤并在此处记录。我发现野外的文档非常零散和贫乏,所以我希望这个答案能成为未来参考的明确地方