Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to push the data from database to application?

I want to push the data from database to application instead of application pull the data. I have installed ms sql server and apache tomcat server. I have my application in apache tomcat, here I made connection to database. Now I want database send the data whenever there is update in data. But all I know is fetch the data from database is not good idea, because application needs to monitor the database for updated data will lead to fire the query for every 5 sec, this is not efficient as well.

I google it I got some answers they are Query Notification here, Sql server Agent Job to schedule the task automatically. If you have any other suggestion please post it.

like image 738
niren Avatar asked Oct 03 '22 18:10

niren


1 Answers

There surely are several possibilities to do that:

  • Implement unsafe CLR trigger
  • Implement unsafe CLR procedure
  • Use xp_cmdshell
  • Call web service
  • Use Query Notification

You can read a little about them in this discussion: Serial numbers, created and modified in SQL Server.

Personally I would prefer Query Notification over other methods, because it already has support fopr various cases (e.g. sync/async communication) and you don't have to reinvent the wheel. And is in your case recommended by Microsoft.

Polling is another method you've mentioned. It's is a more like traditional method and there can be some performance penalties related, but you shouldn't worry about them if you are careful enough. For example, if you already have an authentication built in your application, you can create another column in your Users table that is set if there are any changes related to that user. And then, there can be just a thread in your app that will perform a query every second against this table (even dirty reads with NOLOCK shouldn't be a problem here) and maintain some in-memory structure (e.g. thread-safe dictionary) that says which client should get pushed. Another thread polls your dictionary and when it finds there something for the client, performs a db query that extracts data and sends it to the client. This looks like a lot of unnccessary work, but at the end you get two independent workers which somewhat helps to separate concerns; first one is just an informer which performs 'lightweight' database polling; second one extract real data and performs server push. You can even optimize the push-worker in the way that when it runs, it checks if multiple clients need some data and then executes the select for all of those who need it. You would probably want the second worker to run less frequently than first one.

EDIT

If you wish to use non-.NET technology to achieve the same functionality, you will have to get more into SQL Server Service Broker. Query Notification is a simplified layer built in .NET on top of SQL Server Service Broker, and you would have to build at least part of that layer by yourself. This includes creating queue, message type, service and stored procedures with SEND and RECEIVE on the other side. You will have to take care of the conversation/dialog by yourself. SB is actually a async-messaging world adjusted to work in RDBMS environment, so you will see some new TSQL expressions. However, MSDN is here to help:

  • http://msdn.microsoft.com/en-us/library/ms166061(v=sql.105).aspx
  • http://msdn.microsoft.com/en-us/library/bb522893.aspx

This could help as well: Externally activate non-.NET application from Service Broker

Example on how to code the stuff:

-- First you have to enable SB for your database
USE master
ALTER DATABASE Playground
SET ENABLE_BROKER
GO

USE Playground
GO

-- Then create a message type; usually it will be XML
-- because it's very easy to serialize/deserialize it
CREATE MESSAGE TYPE [//Playground/YourMessageType]
VALIDATION = WELL_FORMED_XML
GO

-- Then create a contract to have a rule for communication
-- Specifies who sends which message type
CREATE CONTRACT [//Playground/YourContract] (
    [//Playground/YourMessageType] SENT BY ANY)
GO

--Creates queues, one for initiator (1) and one for target (2)
CREATE QUEUE MyQueue1
GO
CREATE QUEUE MyQueue2
GO

-- Finally, configure services that 'consume' queues
CREATE SERVICE [//Playground/YourService1]
ON QUEUE MyQueue1 ([//Playground/YourContract])
GO

CREATE SERVICE [//Playground/YourService2] 
ON QUEUE MyQueue2 ([//Playground/YourContract])
GO

-- Now you can send a message from service to service using contract
DECLARE 
    @dHandle uniqueidentifier,
    @Msg nvarchar(max) 

BEGIN DIALOG @dHandle
    FROM SERVICE [//Playground/YourService1]
    TO SERVICE '//Playground/YourService2'
    ON CONTRACT [//Playground/YourContract]
WITH ENCRYPTION = OFF

SELECT @Msg = (
    SELECT TOP 3 *
    FROM Table1
    FOR XML PATH('row'), ROOT('Table1'))

;SEND ON CONVERSATION @dHandle 
MESSAGE TYPE [//Playground/YourMessageType] (@Msg)

PRINT @Msg
GO

-- To get the message on the other end, use RECEIVE
-- Execute this in another query window
DECLARE @dHandle uniqueidentifier
DECLARE @MsgType nvarchar(128)
DECLARE @Msg nvarchar(max)

;RECEIVE TOP(1)
    @dHandle = conversation_handle,
    @Msg = message_body,
    @MsgType = message_type_name
FROM MyQueue2

SELECT @MsgType 
SELECT @Msg

END CONVERSATION @dHandle 
GO
like image 147
OzrenTkalcecKrznaric Avatar answered Oct 09 '22 15:10

OzrenTkalcecKrznaric