Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: Ctrl  назад   1 2 3 4 [5] 6 7   вперед  Ctrl      все
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
WiRuc
Member

Откуда: Воронеж
Сообщений: 1280
Вот пример реализации оповещения на основе Service Broker.
Ограничения: если отсылка сообщения производится в открытой транзации, то реально клиент получит сообщения только в момент commit транзакции. Если будет произведен rollback транзакции, то сообщения посланы не будут.

Установочный скрипт
-- Setup service broker objects needed for support event queue

declare @dbname sysname
set @dbname = db_name()

exec('alter database '+@dbname+ ' set trustworthy on')

IF NOT EXISTS (SELECT 1 FROM sys.databases WHERE name=@dbname and is_broker_enabled = 1)
  exec('alter database '+@dbname+ ' set enable_broker')
go

create message type SBMessageType authorization dbo validation=none 
go

create contract SBContract authorization dbo (SBMessageType sent by any)
go

create queue SBQueue 
go

create service SBService authorization dbo on queue SBQueue (SBContract)
go

-- Associate session with conversation dialog
create table dbo.SBConversation
(
	spid int primary key, 
	conversation_id uniqueidentifier,
	initiator_handle uniqueidentifier,
	target_handle uniqueidentifier
)
go

-- Subsribe event for session
create table dbo.SBSubscribeEvent 
(
	spid int
    constraint fk_SBSubscribeEvent_SBConversation_spid
	foreign key references dbo.SBConversation (spid) 
	on delete cascade on update cascade, 
	eventname nvarchar(255),
	constraint pk_SBSubscribeEvent primary key (spid, eventname)
)
go

-- cleanup conversation needed for event queue
create procedure dbo.up_SBCleanup
with execute as owner
as
set nocount on
set xact_abort on

declare @target_conversation_handle uniqueidentifier, 
	@initiator_conversation_handle uniqueidentifier,
	@conversation_id uniqueidentifier

declare @trancount int
set @trancount = @@trancount

if @trancount = 0
  begin tran

select  @initiator_conversation_handle = initiator_handle,
		@target_conversation_handle = target_handle	
  from dbo.SBConversation with(updlock)
  where spid=@@spid

if @initiator_conversation_handle is not null
  end conversation @initiator_conversation_handle with cleanup

if @target_conversation_handle is not null
  end conversation @target_conversation_handle with cleanup

delete from dbo.SBConversation
  where spid=@@spid

if @trancount = 0
  commit

return 0
go

-- create dialog needed for support event queue
create procedure dbo.up_SBInit
with execute as owner
as
set nocount on
set xact_abort on

declare @target_conversation_handle uniqueidentifier, 
	@initiator_conversation_handle uniqueidentifier,
	@conversation_id uniqueidentifier

declare @receive table (conversation_handle uniqueidentifier)

-- cleanup resource from previous sessions
exec dbo.up_SBCleanup

declare @trancount int
set @trancount = @@trancount

if @trancount = 0
  begin tran

-- start conversation 
begin dialog conversation @initiator_conversation_handle
  from service SBService
  to service 'SBService'
  on contract SBContract
  with encryption=off

-- get conversation id
select @conversation_id = conversation_id
  from sys.conversation_endpoints
  where conversation_handle=@initiator_conversation_handle and is_initiator=1;

-- create endpoint for target
send on conversation @initiator_conversation_handle 
  message type SBMessageType

-- get conversation handle for target
select @target_conversation_handle=conversation_handle
  from sys.conversation_endpoints
  where conversation_id=@conversation_id and is_initiator=0

-- receive init message
waitfor(
    receive conversation_handle
        from SBQueue
        into @receive
        where conversation_handle = @target_conversation_handle
), timeout 5000

insert into dbo.SBConversation
  (spid, conversation_id, initiator_handle, target_handle)
  values
  (@@spid, @conversation_id, @initiator_conversation_handle, @target_conversation_handle)

if @trancount = 0
  commit

return 0
go

-- Subscribe session for receive event
create procedure dbo.up_SBSubscribeEvent 
(
	@eventname nvarchar(255)
)
with execute as owner
as
set nocount on
set xact_abort on

if upper(@eventname)='ALL'
begin
  raiserror('Event name "ALL" is reserved', 16, 1)
  return -1
end

declare @trancount int
set @trancount = @@trancount

if @trancount = 0
  begin tran

if not exists(select 1 from dbo.SBSubscribeEvent with(updlock)
				 where spid=@@spid and eventname=@eventname)
begin
  insert into dbo.SBSubscribeEvent
    (spid, eventname)
    values
    (@@spid, @eventname)
end

if @trancount = 0
  commit tran

return 0
go

-- Drop event from subscribe for session
create procedure dbo.up_SBRejectEvent 
(
	@eventname nvarchar(255)
)
with execute as owner
as
set nocount on
set xact_abort on

delete from dbo.SBSubscribeEvent
  where spid = @@spid and eventname=@eventname

return 0
go

-- Send event to all subscribed sessions
-- If EventName='ALL', then event send for all sessions
-- If called in open tran, then event really send only when transaction commit
create procedure dbo.up_SBSendEvent 
(
	@eventname nvarchar(255),
	@eventdata varbinary(max)=null
)
with execute as owner
as
set nocount on
set xact_abort on

declare @dialog_handle uniqueidentifier

declare @trancount int
set @trancount = @@trancount

if @trancount = 0
  begin tran

if upper(@eventname)='ALL'
  declare curConversation cursor local fast_forward
  for select t1.initiator_handle 
	from dbo.SBConversation t1
else
  declare curConversation cursor local fast_forward
  for select t2.initiator_handle 
	from dbo.SBSubscribeEvent t1
	inner join dbo.SBConversation t2 on t2.spid=t1.spid
	where t1.eventname=@eventname

open curConversation

while (1=1)
begin
  fetch next from curConversation into @dialog_handle
  if @@fetch_status<>0
    break;

  send on conversation @dialog_handle message type SBMessageType (isnull(cast(cast(@eventname as nchar(255)) as binary(500)),0x)+isnull(@eventdata,0x))
end

close curConversation
deallocate curConversation

if @trancount = 0
  commit

return 0
go

-- wait session for subscribed event and return all received event
create procedure dbo.up_SBWaitEvent
with execute as owner
as
set nocount on
set xact_abort on 

declare @receive table 
(
	message_body varbinary(max),
	queuing_order bigint,
	message_sequence_number bigint
)

declare @dialog_handle uniqueidentifier

select @dialog_handle = target_handle 
  from dbo.SBConversation
  where spid=@@spid

if @dialog_handle is null
begin
  raiserror('Event queue not initialize for this session', 16, 1)
  return -1
end

waitfor
(
   receive message_body,
		   queuing_order,
		   message_sequence_number	
     from SBQueue
	 into @receive
	 where conversation_handle=@dialog_handle 
)

-- parse message and return recodset to client
select  message_sequence_number as event_seqnum,
		queuing_order as event_order,		   
		cast(substring(message_body,1,500) as nvarchar(255)) as eventname, 
	 	(case when len(message_body)>500 then substring(message_body,501,len(message_body)-500) end) as eventdata
  from @receive

return 0
go

-- Helper procedure for force cleanup all conversation
create procedure dbo.up_SBCleanupAll 
(
	@all bit = 1
)
with execute as owner
as
set nocount on

declare @conversation_handle uniqueidentifier

declare curConversation cursor local fast_forward
for select conversation_handle 
	from sys.conversation_endpoints 
	where @all = cast(1 as bit) or service_id = (select service_id from sys.services where name = 'SBService')

open curConversation

while (1=1)
begin
  fetch next from curConversation into @conversation_handle
  if @@fetch_status<>0
    break

  end conversation @conversation_handle with cleanup
end

close curConversation
deallocate curConversation

return 0
go

Пример использования:
1 коннект (ожидающий)
-- Инициализация сессии при запуске приложения
exec dbo.up_SBInit
go

exec dbo.up_SBSubscribeEvent 'Event1'
exec dbo.up_SBSubscribeEvent 'Event2'
exec dbo.up_SBSubscribeEvent 'Event3'
go
-- Ожидаем сообщения, при получении обрабатываем на клиенте и запускаем процедуру заново
exec dbo.up_SBWaitEvent
go
-- Очистка сессии при завершении приложения
exec dbo.up_SBCleanup
go

2 коннект (сигнализирующий)
exec up_SBSendEvent 'Event1', 0x1050600
exec up_SBSendEvent 'all' 
27 авг 06, 13:59    [3058411]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
Александр Гладченко
Member

Откуда:
Сообщений: 10802
Блог
Я бы предложил все эти три метода объеденить в одну статью, трёх авторов ;)
27 авг 06, 15:14    [3058547]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 22442
Александр Гладченко
Shocker.Pro

Гм. Как-то не очень внятно написано. С одной стороны, можно сделать вывод, что число исполнителей не может превысить 255. С другой стороны мы знаем, что SQL-сервер способен обслуживать сотни тысяч пользовалетей одновременно, и вряд ли такой лимит может удовлетворить эти нужды.


255 - это по умолчанию в 2000-м, в 2005-м этот параметр сделали динамическим. Никто не мешает увеличить это значение, если нужно...


Сорри а как увеличить это значение в 2000-м? Я его только что потрогал руками
27 авг 06, 18:16    [3058730]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
Александр Гладченко
Member

Откуда:
Сообщений: 10802
Блог
Shocker.Pro

Сорри а как увеличить это значение в 2000-м? Я его только что потрогал руками


USE master
EXEC sp_configure 'show advanced option', '1' -- Options that require a server restart before taking effect
RECONFIGURE
GO
EXEC sp_configure 'max worker threads', '255'
RECONFIGURE WITH OVERRIDE
GO
28 авг 06, 10:12    [3059605]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
А в книжке "Microsoft SQL Server. Полезные алгоритмы от SQL.RU", которая вот-вот появится в продаже, Уфимцев опубликовал новый способ уведомления, который не требует установки на сервер никаких новых объектов, но использующий принцип, очень похожий на https://www.sql.ru/articles/mssql/02040201AlertServiceForSQLserv.shtml ,
с теми же достоинства метода. Там вместо дополнительной расширенной процедуры предлагается использовать встроенные механизмы SQL-сервера, не совсем документированные, но как оказалось, весьма подходящие для решаемой задачи.


----------------------------------------------------------------
Да полно-те Вам. Не стоит благодарности.
29 авг 06, 11:50    [3065133]     Ответить | Цитировать Сообщить модератору
 Не удержусь еще от одного замечания  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
Помимо всех вышеперечисленных методов, реализуемых, как на основе провайдера (ADO,ADO.NET), внешних приблуд к SQL (SB+NS или отдельная TCP/IP прокси), MSMQ, SQL-MAIL и пр. есть еще ОЧЕНЬ интересный метод, который вообще ускользнул от обсуждения.

В ASP.NET2 - есть такая фишка - зависимость обьекта CASHE от SQL-рекордсетов - класс System.Web.Caching.SqlCacheDependency
System.Web.Caching.Cache конфигурится прямо из WEB-конфиг. Там же указывается интервал опроса рекордсета. Те на самом нижнем уровне (который в приложении не виден и обеспечивается собственно средой ASP2) - это просто опрос. Но на верхнем уровне приложения - это ВСЕГДА АКТУАЛЬНЫЙ РЕКОРДСЕТ в кеше, который обеспечивается именно встроенными в среду ASP2 обьектами.

Это как бы еще подход, который с одной стороны вообще исключает необходимость оповещения, с другой стороны - тут и кнопки Refresh никакой нет.
30 авг 06, 17:24    [3072862]     Ответить | Цитировать Сообщить модератору
 Re: Не удержусь еще от одного замечания  [new]
WiRuc
Member

Откуда: Воронеж
Сообщений: 1280
sysadm2000
Помимо всех вышеперечисленных методов, реализуемых, как на основе провайдера (ADO,ADO.NET), внешних приблуд к SQL (SB+NS или отдельная TCP/IP прокси), MSMQ, SQL-MAIL и пр. есть еще ОЧЕНЬ интересный метод, который вообще ускользнул от обсуждения.

В ASP.NET2 - есть такая фишка - зависимость обьекта CASHE от SQL-рекордсетов - класс System.Web.Caching.SqlCacheDependency
System.Web.Caching.Cache конфигурится прямо из WEB-конфиг. Там же указывается интервал опроса рекордсета. Те на самом нижнем уровне (который в приложении не виден и обеспечивается собственно средой ASP2) - это просто опрос. Но на верхнем уровне приложения - это ВСЕГДА АКТУАЛЬНЫЙ РЕКОРДСЕТ в кеше, который обеспечивается именно встроенными в среду ASP2 обьектами.

Это как бы еще подход, который с одной стороны вообще исключает необходимость оповещения, с другой стороны - тут и кнопки Refresh никакой нет.


Насколько я понимаю, это те же самые "Уведомления в ADO.NET", ссылку на статую приводили выше. Вы лучше обратите внимание на ту кучу ограничений, которые накладываются на запрос, чтобы можно было воспользоваться этой фичей. И не понятно, как все это будет работать, если для выборок используются ХП, а не прямые запросы.
30 авг 06, 18:22    [3073241]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
Насколько я понимаю, это те же самые "Уведомления в ADO.NET" 
Нет, это не связано с уведомлениями, отправляемыми SB. Ща попробую сделать тестик этой фишки и положу сюда.
30 авг 06, 18:48    [3073353]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
WiRuc
Member

Откуда: Воронеж
Сообщений: 1280
Уведомления в ADO.NET и Service Broker совершенно разные вещи! Посмотрите в BOL.
30 авг 06, 18:58    [3073407]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
Ну я разобрался досконально как эта фишка работает:

1.В приложении составляем вот такой конфигурационный файл
	<connectionStrings>
		<add name="SH_Price" connectionString="Data Source=VS2005;Initial Catalog=SH;Integrated Security=True" providerName="System.Data.SqlClient"/>
	</connectionStrings>
	<system.web>
		<caching>
			<sqlCacheDependency enabled="true" pollTime="1000"  >
				<databases>
					<add name="SH" connectionStringName="SH_Price" />
				</databases> 
			</sqlCacheDependency>
		</caching>
Здесь: VS2005 - имя SQL-сервера, SH - имя базы в которой ведется работа. Табла, с которой проводились тесты, называется MyGroup.

2.В Application_Start выдаем:
        'это запускается ОДИН раз чтобы создать в базе нужную таблу и триггера
        System.Web.Caching.SqlCacheDependencyAdmin.EnableNotifications(System.Configuration.ConfigurationManager.ConnectionStrings("SH_Price").ConnectionString)
        System.Web.Caching.SqlCacheDependencyAdmin.EnableTableForNotifications(System.Configuration.ConfigurationManager.ConnectionStrings("SH_Price").ConnectionString, "MyGroup")
        'это контроль
        'System.Web.Caching.SqlCacheDependencyAdmin.GetTablesEnabledForNotifications(System.Configuration.ConfigurationManager.ConnectionStrings("SH_Price").ConnectionString)

3. Вышеуказанные две строчки создают в заданной базе:
/* Create notification table */ 
IF NOT EXISTS (SELECT name FROM sysobjects WITH (NOLOCK) WHERE name = 'AspNet_SqlCacheTablesForChangeNotification' AND type = 'U') 
   IF NOT EXISTS (SELECT name FROM sysobjects WITH (TABLOCKX) WHERE name = 'AspNet_SqlCacheTablesForChangeNotification' AND type = 'U') 
      CREATE TABLE dbo.AspNet_SqlCacheTablesForChangeNotification (
      tableName             NVARCHAR(450) NOT NULL PRIMARY KEY,
      notificationCreated   DATETIME NOT NULL DEFAULT(GETDATE()),
      changeId              INT NOT NULL DEFAULT(0)
      )

/* Create polling SP */
IF NOT EXISTS (SELECT name FROM sysobjects WITH (NOLOCK) WHERE name = 'AspNet_SqlCachePollingStoredProcedure' AND type = 'P') 
   IF NOT EXISTS (SELECT name FROM sysobjects WITH (TABLOCKX) WHERE name = 'AspNet_SqlCachePollingStoredProcedure' AND type = 'P') 
   EXEC('CREATE PROCEDURE dbo.AspNet_SqlCachePollingStoredProcedure AS
         SELECT tableName, changeId FROM dbo.AspNet_SqlCacheTablesForChangeNotification
         RETURN 0')

/* Create SP for registering a table. */ 
IF NOT EXISTS (SELECT name FROM sysobjects WITH (NOLOCK) WHERE name = 'AspNet_SqlCacheRegisterTableStoredProcedure' AND type = 'P') 
   IF NOT EXISTS (SELECT name FROM sysobjects WITH (TABLOCKX) WHERE name = 'AspNet_SqlCacheRegisterTableStoredProcedure' AND type = 'P') 
   EXEC('CREATE PROCEDURE dbo.AspNet_SqlCacheRegisterTableStoredProcedure 
             @tableName NVARCHAR(450) 
         AS
         BEGIN

         DECLARE @triggerName AS NVARCHAR(3000) 
         DECLARE @fullTriggerName AS NVARCHAR(3000)
         DECLARE @canonTableName NVARCHAR(3000) 
         DECLARE @quotedTableName NVARCHAR(3000) 

         %af_src_comm_3 
         SET @triggerName = REPLACE(@tableName, ''['', ''__o__'') 
         SET @triggerName = REPLACE(@triggerName, '']'', ''__c__'') 
         SET @triggerName = @triggerName + ''_AspNet_SqlCacheNotification_Trigger'' 
         SET @fullTriggerName = ''dbo.['' + @triggerName + '']'' 

         %af_src_comm_4 
         %af_src_comm_5 
         IF (CHARINDEX(''.'', @tableName) <> 0 OR 
             CHARINDEX(''['', @tableName) <> 0 OR 
             CHARINDEX('']'', @tableName) <> 0) 
             SET @canonTableName = @tableName 
         ELSE 
             SET @canonTableName = ''['' + @tableName + '']'' 

         %af_src_comm_6 
         IF (SELECT OBJECT_ID(@tableName, ''U'')) IS NULL 
         BEGIN 
             RAISERROR (''00000001'', 16, 1) 
             RETURN 
         END 

         BEGIN TRAN
         %af_src_comm_7 
         IF NOT EXISTS (SELECT tableName FROM dbo.AspNet_SqlCacheTablesForChangeNotification WITH (NOLOCK) WHERE tableName = @tableName) 
             IF NOT EXISTS (SELECT tableName FROM dbo.AspNet_SqlCacheTablesForChangeNotification WITH (TABLOCKX) WHERE tableName = @tableName) 
                 INSERT  dbo.AspNet_SqlCacheTablesForChangeNotification 
                 VALUES (@tableName, GETDATE(), 0)

         %af_src_comm_8 
         SET @quotedTableName = QUOTENAME(@tableName, '''''''') 
         IF NOT EXISTS (SELECT name FROM sysobjects WITH (NOLOCK) WHERE name = @triggerName AND type = ''TR'') 
             IF NOT EXISTS (SELECT name FROM sysobjects WITH (TABLOCKX) WHERE name = @triggerName AND type = ''TR'') 
                 EXEC(''CREATE TRIGGER '' + @fullTriggerName + '' ON '' + @canonTableName +''
                       FOR INSERT, UPDATE, DELETE AS BEGIN
                       SET NOCOUNT ON
                       EXEC dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure N'' + @quotedTableName + ''
                       END
                       '')
         COMMIT TRAN
         END
   ')

/* Create SP for updating the change Id of a table. */ 
IF NOT EXISTS (SELECT name FROM sysobjects WITH (NOLOCK) WHERE name = 'AspNet_SqlCacheUpdateChangeIdStoredProcedure' AND type = 'P') 
   IF NOT EXISTS (SELECT name FROM sysobjects WITH (TABLOCKX) WHERE name = 'AspNet_SqlCacheUpdateChangeIdStoredProcedure' AND type = 'P') 
   EXEC('CREATE PROCEDURE dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure 
             @tableName NVARCHAR(450) 
         AS

         BEGIN 
             UPDATE dbo.AspNet_SqlCacheTablesForChangeNotification WITH (ROWLOCK) SET changeId = changeId + 1 
             WHERE tableName = @tableName
         END
   ')

/* Create SP for unregistering a table. */ 
IF NOT EXISTS (SELECT name FROM sysobjects WITH (NOLOCK) WHERE name = 'AspNet_SqlCacheUnRegisterTableStoredProcedure' AND type = 'P') 
   IF NOT EXISTS (SELECT name FROM sysobjects WITH (TABLOCKX) WHERE name = 'AspNet_SqlCacheUnRegisterTableStoredProcedure' AND type = 'P') 
   EXEC('CREATE PROCEDURE dbo.AspNet_SqlCacheUnRegisterTableStoredProcedure 
             @tableName NVARCHAR(450) 
         AS
         BEGIN

         BEGIN TRAN
         DECLARE @triggerName AS NVARCHAR(3000) 
         DECLARE @fullTriggerName AS NVARCHAR(3000)
         SET @triggerName = REPLACE(@tableName, ''['', ''__o__'') 
         SET @triggerName = REPLACE(@triggerName, '']'', ''__c__'') 
         SET @triggerName = @triggerName + ''_AspNet_SqlCacheNotification_Trigger'' 
         SET @fullTriggerName = ''dbo.['' + @triggerName + '']'' 

         %af_src_comm_11 
         IF EXISTS (SELECT name FROM sysobjects WITH (NOLOCK) WHERE name = ''AspNet_SqlCacheTablesForChangeNotification'' AND type = ''U'') 
             IF EXISTS (SELECT name FROM sysobjects WITH (TABLOCKX) WHERE name = ''AspNet_SqlCacheTablesForChangeNotification'' AND type = ''U'') 
             DELETE FROM dbo.AspNet_SqlCacheTablesForChangeNotification WHERE tableName = @tableName 

         %af_src_comm_12 
         IF EXISTS (SELECT name FROM sysobjects WITH (NOLOCK) WHERE name = @triggerName AND type = ''TR'') 
             IF EXISTS (SELECT name FROM sysobjects WITH (TABLOCKX) WHERE name = @triggerName AND type = ''TR'') 
             EXEC(''DROP TRIGGER '' + @fullTriggerName) 

         COMMIT TRAN
         END
   ')

/* Create SP for querying all registered table */ 
IF NOT EXISTS (SELECT name FROM sysobjects WITH (NOLOCK) WHERE name = 'AspNet_SqlCacheQueryRegisteredTablesStoredProcedure' AND type = 'P') 
   IF NOT EXISTS (SELECT name FROM sysobjects WITH (TABLOCKX) WHERE name = 'AspNet_SqlCacheQueryRegisteredTablesStoredProcedure' AND type = 'P') 
   EXEC('CREATE PROCEDURE dbo.AspNet_SqlCacheQueryRegisteredTablesStoredProcedure 
         AS
         SELECT tableName FROM dbo.AspNet_SqlCacheTablesForChangeNotification   ')

/* Create roles and grant them access to SP  */ 
IF NOT EXISTS (SELECT name FROM sysusers WHERE issqlrole = 1 AND name = N'aspnet_ChangeNotification_ReceiveNotificationsOnlyAccess') 
    EXEC sp_addrole N'aspnet_ChangeNotification_ReceiveNotificationsOnlyAccess' 

GRANT EXECUTE ON dbo.AspNet_SqlCachePollingStoredProcedure to aspnet_ChangeNotification_ReceiveNotificationsOnlyAccess
После чего второй строкой создается триггер в заданной базе. Обратите внимание, что все это пока потребовало всего двух строк кода в приложении, причем выдать их надо ВСЕГО ОДИН РАЗ.

4.Далее мы конфигурируем зависимость, ну это уже пошло чисто ASP2-программирование. Ну так для справки - это выглядит так:
        Dim X As New SqlDataSource
        X.DataSourceMode = SqlDataSourceMode.DataReader
        X.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("SH_Price").ConnectionString
        X.SelectCommand = "GetMyGroupForXML"
        Dim DR As Data.SqlClient.SqlDataReader = X.Select(New DataSourceSelectArguments)
        If DR.Read Then
            Dim XML_string As String = DR.GetSqlString(0)
            Dim MySqlDependency = New SqlCacheDependency("SH", "MyGroup")
            Cache.Insert("MyXML", XML_string, MySqlDependency)
        End If
        DR.Close()

5. Собственно все. Теперь в обьекте MyXML всегда актуальные - курсы валют, текущие остатки на складе, брак, товар со скидкой и так далее. XmlDataSource грузится этими данными
        XmlDataSource1.Data = Cache("MyXML")
        XmlDataSource1.DataBind()
И собственно все. Все контролы на страничке (сетки, деревья, комбешники) - они просто привязаны на данные в XMLDataSource и просто отображают это на страничку. При желании можно обрабатывать события изменения данных в Кеше.

6.Ну а профайлер показывает вот что:

К сообщению приложен файл. Размер - 0Kb
30 авг 06, 22:14    [3073972]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
Уведомления в ADO.NET и Service Broker совершенно разные вещи! Посмотрите в BOL.
Чето меня гложут смутные сомнения по поводу достоверности этого вашего утверждения.
Ведь вся работа ADO.NET-уведомлений основана на работе с обьектом QUEUE.
А апишники эти инкапсулированы в компонент ServiceBroker. Хотя я допускаю вариант, что
DROP QUEUE [dbo].[ServiceBrokerQueue] 
не отключит уведомления ADO.NET. Надо понять также в каких именно очередях могут продвигаться ADO.NET уведомления - это мне пока не ясно.

В любом случае мне это интересно расковырять, ибо я не применял ADO.NET-уведомления в практическом плане именно из-за зависимости от SB.
Я постараюсь сегодня найти время и составить тесты на минимальные требования к ADO.NET-уведомлениям. Результат тестов выложу.
31 авг 06, 09:26    [3074639]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
Кстати мне кто-нибудь подскажет как в целом остановить и вновь запустить SB - а не по отдельным очередям.
31 авг 06, 09:29    [3074655]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
GreenSunrise
Member

Откуда:
Сообщений: 12310
Офигеть. sysadm2000 научился код выкладывать не в виде картинок, а в виде текста! То-то я думаю, похолодало...
31 авг 06, 11:48    [3075703]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
GreenSunrise
Офигеть. sysadm2000 научился код выкладывать не в виде картинок, а в виде текста! То-то я думаю, похолодало...

Поди, кнопка Print Screen западать стала. ;)
31 авг 06, 11:50    [3075725]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
Поди, кнопка Print Screen западать стала. ;)
Нет, просто больше одного рисунка нельзя загрузить - пришлось текстом.

Что касается ADO.NET-уведомлений, то как я и предполагал изначально - это глюк еще тот. Я так и не сумел его настроить.
Первое. Я не смог подобрать опцию для нотификации с конструктором, где указывается опция - и не нашел, какая она должна быть. Третий фрагмент рисунка.
Второе. Сама нотификация отчего-то получается INVALID, что видно на рисунке (первый фрагмент).
Третье. Я смог сделать доступным сервис брокера ТОЛЬКО для некоторых своих баз. Включается и проверяется он так
ALTER DATABASE sva_new SET ENABLE_BROKER
select is_broker_enabled from sys.databases where database_id=db_id()
Четвертое Ну как и ожидалось, ADO.NET-уведомления, конечно - это чистейшая финкциональность брокера, его обьекты. Они видны в отладчике в обьекте Command и, собственно говоря в базе (второй фрагмент)
Пятое. Последний фрагмент рисунка - специально для WiRuc - я уже говорил, что брокер запустился у меня ЛИШЬ в некоторых базах. В остальных базах - попытка сделать ADO.NET оповещение (несмотря на все мои потуги что-либо разблокировать, перезагрузиться и тд) - окончиласб вот так - самых нижний рисунок.
Шестое.Все-все имена, связанные с ADO.NET-уведомлениями, начинаются с префикса NotificationService, из чего закрадываются законные подозрения, что SB - это просто механизм обслуживания обьектов QUEUE, грубо говоря - его совершенно недостаточно для ADO.NET-уведомлений.

Как я и предполагал, это - наиболее отстойный и нелепый способ поолучения уведомлений из всех рассмотренных выше.

К сообщению приложен файл. Размер - 0Kb
31 авг 06, 17:16    [3078332]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
GreenSunrise
Member

Откуда:
Сообщений: 12310
Гавриленко Сергей Алексеевич
Поди, кнопка Print Screen западать стала. ;)

Гыыыы :-))))) Реально - пять :-)

sysadm2000
Нет, просто больше одного рисунка нельзя загрузить - пришлось текстом.

О! Есть такая штука - пайнт. Туда можно мноооого рисунков напихать и слабать из них один. Осваивайте, не пожалеете! (правда, мы пожалеем :-P)

Кстати, простите за нескромный вопрос, что вы делаете, когда приводимый текст не влазит на экран? Скриншотите, потом прокручиваете вниз, опять скриншотите, потом еще вниз... и склеиваете это все?

Хе-хе-хе, можно разрешение экрана увеличить... До определенной степени поможет.
31 авг 06, 17:49    [3078615]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
2GreenSunrise: к счастью, размер прикладываемого файла ограничен 70 Кб.
31 авг 06, 17:51    [3078629]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
О! Есть такая штука - пайнт. Туда можно мноооого рисунков напихать и слабать из них один. Осваивайте, не пожалеете!
Теоретические подходы - они рулят, да. Но к сожалению, только теоретически. Если у вас скриншотофобобия в такой тяжелой форме, то почему вы не работаете во FreeBSD с выключенным GUI?

Увы, Windows (есть такая штука) - он устроен так, что все самое ценное выпархивает там в окошках - ну тот же формат опции в SQLDependency в моем посту выше. И никаких, никаких более способов не существует зафиксировать это сообщение. Кстати формат этой опции (судя по скрину является текстовой строкой, скомбинированной из трех ключей), что совсем не соответствует документации, где это просто INT32 перечисление.

Увидеть без огромного и гиморойного текста, что событие уведомления принесло информацию "INVALID", увы, без скриншота тоже невозможно - расскажите мне, как ПРОСТО выложить это в текстовую строку в Windows-приложении (когда структрура обьекта e особо непонятно) - сериализовывать все классы, методы и свойства в типе е?

После того, как вы мне прочитаете лекцию про сериализацию типов через Reflection - Я вам задам следующий вопрос - п процессе эспериментов я сделал пару дестков запусков, подбирая параметр - я спрошу у вас - как вы поставите в соотвествие 70 тестовых строк с ошибками 70-ти вариантам запуска проги с различным исходным кодом?

Обдумайте еще раз чем Windows отличается от MS-DOS или FreeBSD м отключенным GUI и выберите - или пить пилюли от скриншотофобии или перейти в MS-DOS...
31 авг 06, 18:16    [3078777]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
WiRuc
Member

Откуда: Воронеж
Сообщений: 1280
WiRuc
Уведомления в ADO.NET и Service Broker совершенно разные вещи! Посмотрите в BOL.

Был неправ:) Внутренний механизм уведомлений похоже основан на возможностях SB.
А приведенный вами фрагмент для ASP.NET - это обычный опрос БД с заданным интервалом времени. Такое самому можно соорудить в два счета.
31 авг 06, 18:17    [3078785]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
WiRuc
Member

Откуда: Воронеж
Сообщений: 1280
sysadm2000
Увидеть без огромного и гиморойного текста, что событие уведомления принесло информацию "INVALID", увы, без скриншота тоже невозможно - расскажите мне, как ПРОСТО выложить это в текстовую строку в Windows-приложении (когда структрура обьекта e особо непонятно) - сериализовывать все классы, методы и свойства в типе е?

System.Diagnostics.Trace.WriteLine()
31 авг 06, 18:20    [3078797]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
sysadm2000
Увы, Windows (есть такая штука) - он устроен так, что все самое ценное выпархивает там в окошках - ну тот же формат опции в SQLDependency в моем посту выше.

А Вы в курсе, что в каждом окошке этой штуки работает кнопка Ctrl+C? А при оформлении сообщения - Ctrl+V? Или Вы думаете, что все бросятся такскать монитор к сканеру (или сканер к монитору), чтобы скопировать Ваш код или сообщение об ошибке?
31 авг 06, 18:20    [3078801]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
А приведенный вами фрагмент для ASP.NET - это обычный опрос БД с заданным интервалом времени
Конечно. Просто это пример подхода - вы видели - там же всего пару строк исходного текста, а все триггера и прочее создалось само...
И в отличии от ADO.NET уведомлений работает стабильно и преотлично...

Кстати, как вы относитесь к мысли, что ADO.NET-уведомления основаны НЕ ТОЛЬКО на SB, но и на NS? Уж больно странные имена... Но расковыривать дальше у меня уже нет ни времени ни желания - я в очередной раз убедился что это просто мертворожденный выкидыш от микрософт...

Еще вопрос к вам, я вижу вы лихо расправляетесь не только с EventHandler и Monitor, но и с SB. Почему он доступен у меня не для всех баз?
31 авг 06, 18:24    [3078816]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
монитор к сканеру 
Ну насчет монитора к сканеру - это сильное заявление. Сильнее даже, чем "Кнопка Refresh рулит". При наличии желания требуется пять сек (на выделение блока распознавания) в любой OCX-проге.
Насчет CTRL-C - не в курсе. Расскажите как скопировать сообщение с ошибкой (куда?) - в текстовый файл?
31 авг 06, 18:28    [3078839]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
sysadm2000
Member

Откуда: Москва
Сообщений: 1212
System.Diagnostics.Trace.WriteLine()
И куда мне посмотреть, чтоб увидеть содержимое "e" (и код, который привел именно к такому "e")

К сообщению приложен файл. Размер - 0Kb
31 авг 06, 18:34    [3078876]     Ответить | Цитировать Сообщить модератору
 Re: Уведомление клиента о событии на SQL-сервере! НОВОЕ РЕШЕНИЕ!  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
sysadm2000
При наличии желания требуется пять сек (на выделение блока распознавания) в любой OCX-проге.

О, по силе заявлений Вы мне дадите 100 очков вперед.

sysadm2000
Расскажите как скопировать сообщение с ошибкой (куда?) - в текстовый файл?

Выделить текст ошибки, (если можно), нажать Ctrl+C (даже если выделить текст нельзя), создать новый текстовый файлик (тоже написать, как сделать?), открыть его, допустим, блокнотом, и нажать Ctrl+V.
31 авг 06, 18:35    [3078883]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 2 3 4 [5] 6 7   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить