Showing posts with label writting. Show all posts
Showing posts with label writting. Show all posts

Wednesday, March 21, 2012

Problems communicating across services.

Hello,

I am writting two applications that talk to each other. I create a service and then a dialog that points to Client2Service which means it is talking to it self. When I do that it works because I get pack the string "client1" which I am forcing it to send if it is calling ServiceProc in client1. I cahnge the Client2Service to Client1Service and it does not work any more. I do not understand why but am guessing it has something to do with the way I have the database setup. The installation script is bellow. Please share your thoughts because I am running out of ideas.

USE master;

GO

CREATE DATABASE ssb_FloorSystem;

GO

USE ssb_FloorSystem;

GO

CREATE MESSAGE TYPE Request VALIDATION = None;

CREATE MESSAGE TYPE Response VALIDATION = None;

GO

CREATE CONTRACT MessageTalk(

Request SENT BY INITIATOR,

Response SENT BY TARGET

);

GO

-- Install assemblies

BEGIN TRY

CREATE ASSEMBLY BrokerLibraryAssembly

FROM 'c:\ServiceBroker\Client1\Client1\bin\Debug\ServiceBrokerInterface.dll'

END TRY

BEGIN CATCH

-- Catch and handle exception

END CATCH;

GO

BEGIN TRY

CREATE ASSEMBLY SqlClient1BrokerServiceAssembly

FROM 'c:\ServiceBroker\Client1\Client1\bin\Debug\SqlClient1BrokerService.dll'

END TRY

BEGIN CATCH

-- Catch and handle exception

END CATCH;

GO

BEGIN TRY

CREATE ASSEMBLY SqlClient2BrokerServiceAssembly

FROM 'c:\ServiceBroker\Client2\Client2\bin\Debug\SqlClient2BrokerService.dll'

END TRY

BEGIN CATCH

-- Catch and handle exception

END CATCH;

GO

CREATE PROCEDURE Client1ServiceProc

AS

EXTERNAL NAME SqlClient1BrokerServiceAssembly.[SqlBrokerServiceNS.SqlBrokerService].ServiceProc

GO

CREATE PROCEDURE Client2ServiceProc

AS

EXTERNAL NAME SqlClient2BrokerServiceAssembly.[SqlBrokerServiceNS.SqlBrokerService].ServiceProc

GO

CREATE QUEUE Client1ServiceQueue

WITH

STATUS = ON,

RETENTION = ON,

ACTIVATION (

STATUS = ON,

PROCEDURE_NAME = Client2ServiceProc,

MAX_QUEUE_READERS = 4,

EXECUTE AS SELf

)

ON [default];

GO

CREATE QUEUE Client2ServiceQueue

WITH

STATUS = ON,

RETENTION = ON,

ACTIVATION (

STATUS = ON,

PROCEDURE_NAME = Client1ServiceProc,

MAX_QUEUE_READERS = 4,

EXECUTE AS SELf

)

ON [default];

GO

CREATE QUEUE [dbo].[ClientQueue] WITH STATUS = ON;

GO

CREATE SERVICE Client1Service ON QUEUE Client1ServiceQueue (

MessageTalk,

[http://schemas.microsoft.com/SQL/ServiceBroker/ServiceEcho]

);

GO

CREATE SERVICE Client2Service ON QUEUE Client2ServiceQueue (

MessageTalk,

[http://schemas.microsoft.com/SQL/ServiceBroker/ServiceEcho]

);

GO

CREATE SERVICE HelloWorldClient ON QUEUE ClientQueue (

MessageTalk,

[http://schemas.microsoft.com/SQL/ServiceBroker/ServiceEcho]

);

GO

EXEC sp_configure 'clr enabled', 1

GO

RECONFIGURE WITH OVERRIDE

GO

USE master;

GO

Thanks,

Scott Allison...

How are you beginning the dialog and sending the message? Did you try to diagnose the problem by looking at (i.e. simply doing a select * from...):

1. the initiator queue

2. the target quueue

3. sys.transmission_queue

|||

Hello Rushi,

I tried

select * from sys.dm_broker_activated_tasks

select * from sys.transmission_queue

and they both returned nothing. The code to send it bellow.

try

{

// Create a connection

conn = new SqlConnection(

"Initial Catalog=ssb_FloorSystem; Data Source=localhost;Integrated Security=SSPI;");

// Open the connection

conn.Open();

// Begin a transaction

tran = conn.BeginTransaction();

// Create a service object

client = new Service("HelloWorldClient", conn, tran);

// Set the FetchSize to 1 since we will receive one message at a time

// i.e. use RECEIVE TOP(1)

client.FetchSize = 1;

// Begin a dialog with the HelloWorld service

dialog = client.BeginDialog(

"Client1Service",

null,

"MessageTalk",

TimeSpan.FromMinutes(1),

false,

conn,

tran);

// Create an empty request message

MemoryStream body = new MemoryStream(Encoding.ASCII.GetBytes(Msg));

Message request = new Message("Request", body);

// Send the message to the service

dialog.Send(request, conn, tran);

tran.Commit(); // Message isn't sent until transaction has been committed

}

catch

{

tran.Rollback();

}

While the Code to recieve is bellow.

public string GetMessage(SqlConnection conn, Conversation dialog, Service client, SqlTransaction tran)

{

TextReader reader = null;

try

{

// Begin a transaction

tran = conn.BeginTransaction();

Console.WriteLine("\nTransaction 1 begun");

client.WaitforTimeout = TimeSpan.FromSeconds(5);

if (client.GetConversation(dialog, conn, tran) == null)

{

Console.WriteLine("No message received - Ending dialog with Error");

dialog.EndWithError(1, "no response within 5 seconds.", conn, tran);

tran.Commit();

Console.WriteLine("Transaction 2 committed");

conn.Close();

Console.WriteLine("\nConnection closed - exiting");

return "";

}

// Fetch the message from the conversation

Message response = dialog.Receive();

// Output the message to the Console

//Console.WriteLine("Message received of type '" + response.Type + "'");

if (response.Body != null)

{

reader = new StreamReader(response.Body);

}

// End the conversation

dialog.End(conn, tran);

Console.WriteLine("Ended Dialog");

//tran.Commit(); // Remember to commit again

Console.WriteLine("Transaction 2 committed");

// Close the database connection

conn.Close();

Console.WriteLine("\nConnection closed - exiting");

if (response.Body != null)

return reader.ReadToEnd();

return "";

}

catch (ServiceException e)

{

Console.WriteLine("An exception occurred - {0}\n", e.ToString());

if (tran != null)

{

tran.Rollback();

Console.WriteLine("\nTransaction rolled back");

}

if (conn != null)

{

conn.Close();

Console.WriteLine("\nConnection closed - exiting");

}

return "";

}

finally

{

if (reader != null)

reader.Close();

Console.WriteLine();

Console.WriteLine("Press Enter to Exit");

Console.ReadLine();

}

}

Thanks,

Scott Allison...

Wednesday, March 7, 2012

Problem with writting a Report (SQL slow running)

Hi

I am trying to write a report that calculates the average number of sales
over 7, 14, 31 and 365 days for each hourly period of the day. the problem
is it takes over 4 minutes to run.

e.g.
Average Xactions per Hour
7 Days 14 Days 31 Days 365 Days
00:00 - 01:00 1,141.6 579.2 261.6 28.8
01:00 - 02:00 1,298.0 649.6 293.4 30.0

The report was use to be purely ASP running SQL Statements.
I then changed it to ASP Running a SP 24 times - this reduced running time
by about 1 minute.
I then changed it so that the stored proc looped internally 24 times and
returns the data.

I have ran the Index Tuning Wizard on the SQL and Implemented the indexes
suggested - this actually increase execution time by 20 seconds.

Below is the stored procedure I am currently using that loops internally 24
times and returns the data.

Can anyone suggest a better way / any improvements I could make ?

Many Thanks

Steve

-----------------------
--------

CREATE procedure ams_RPT_Gen_Stats
@.strResult varchar(8) = 'Failure' output,
@.strErrorDesc varchar(512) = 'SP Not Executed' output,
@.strTest varchar(1),
@.strCurrency varchar(3),
@.strVFEID varchar(16)
as
declare @.strStep varchar(32)

set @.strStep = 'Start of Stored Proc'

/* start insert sp code here */

create table ##Averages (
TheHour varchar(2),
Day7Avge float ,
Day14Avge float ,
Day31Avge float ,
Day365Avge float
)

declare @.numHour varchar(2)
declare @.strSQL varchar(2000)
declare @.Wholesalers varchar(64)

declare MyHours cursor FORWARD_ONLY READ_ONLY for
select convert(char(2), timestamp,14) as TheHour
from xactions
group by convert(char(2), timestamp,14)
order by convert(char(2), timestamp,14)

if @.strTest = 'Y'
select @.Wholesalers = VALUE FROM BUSINESSRULES WHERE NAME =
'TEST_Wholesalers'

open MyHours

fetch next from MyHours into @.numHour

while @.@.fetch_status = 0

begin

set @.strSQL = 'insert into ##Averages (TheHour, Day7Avge) ( select ''' +
@.numHour + ''', ' +
'count(*) / 7.00 ' +
'FROM ' +
'XACTIONS INNER JOIN ' +
'RETAILER ON XACTIONS.RETAILERID = RETAILER.RETAILERID ' +
'WHERE ' +
'(DATEDIFF(DAY , xactions.timestamp , GETDATE() ) < 8) and ' +
'xactions.xactiontotal <> 0 and ' +
' convert(char(2) , timestamp, 14) = ''' + @.numHour + ''' '

if @.strTest = 'Y'
set @.strSQL = @.strSQL + ' and retailer.BillOrgID not in (' +
@.Wholesalers + ') '

if @.strCurrency <> '*'
set @.strSQL = @.strSQL + ' and xactions.XACTIONCURRENCY = ''' +
@.strCurrency + ''' '

if @.strVFEID <> '*'
set @.strSQL = @.strSQL + ' and xactions.VFEID = ''' + @.strVFEID + ''''
set @.strSQL = @.strSQL + ')'

exec ( @.strSQL )

set @.strSQL = 'update ##Averages set Day14Avge = ( select ' +
'count(*) / 14.00 ' +
'FROM ' +
'XACTIONS INNER JOIN ' +
'RETAILER ON XACTIONS.RETAILERID = RETAILER.RETAILERID ' +
'WHERE ' +
'(DATEDIFF(DAY , xactions.timestamp , GETDATE() ) < 15) and ' +
'xactions.xactiontotal <> 0 and ' +
' convert(char(2) , timestamp, 14) = ''' + @.numHour + ''' '

if @.strTest = 'Y'
set @.strSQL = @.strSQL + ' and retailer.BillOrgID not in (' +
@.Wholesalers + ') '

if @.strCurrency <> '*'
set @.strSQL = @.strSQL + ' and xactions.XACTIONCURRENCY = ''' +
@.strCurrency + ''' '

if @.strVFEID <> '*'
set @.strSQL = @.strSQL + ' and xactions.VFEID = ''' + @.strVFEID + ''' '

set @.strSQL = @.strSQL + ') where TheHour = ''' + @.numHour + ''' '

exec ( @.strSQL )

set @.strSQL = 'update ##Averages set Day31Avge = ( select ' +
'count(*) / 31.00 ' +
'FROM ' +
'XACTIONS INNER JOIN ' +
'RETAILER ON XACTIONS.RETAILERID = RETAILER.RETAILERID ' +
'WHERE ' +
'(DATEDIFF(DAY , xactions.timestamp , GETDATE() ) < 32) and ' +
'xactions.xactiontotal <> 0 and ' +
' convert(char(2) , timestamp, 14) = ''' + @.numHour + ''' '

if @.strTest = 'Y'
set @.strSQL = @.strSQL + ' and retailer.BillOrgID not in (' +
@.Wholesalers + ') '

if @.strCurrency <> '*'
set @.strSQL = @.strSQL + ' and xactions.XACTIONCURRENCY = ''' +
@.strCurrency + ''' '

if @.strVFEID <> '*'
set @.strSQL = @.strSQL + ' and xactions.VFEID = ''' + @.strVFEID + ''' '

set @.strSQL = @.strSQL + ' ) where TheHour = ''' + @.numHour + ''' '

exec ( @.strSQL )

set @.strSQL = 'update ##Averages set Day365Avge = ( select ' +
'count(*) / 365.00 ' +
'FROM ' +
'XACTIONS INNER JOIN ' +
'RETAILER ON XACTIONS.RETAILERID = RETAILER.RETAILERID ' +
'WHERE ' +
'(DATEDIFF(DAY , xactions.timestamp , GETDATE() ) < 366) and ' +
'xactions.xactiontotal <> 0 and ' +
' convert(char(2) , timestamp, 14) = ''' + @.numHour + ''' '

if @.strTest = 'Y'
set @.strSQL = @.strSQL + ' and retailer.BillOrgID not in (' +
@.Wholesalers + ') '

if @.strCurrency <> '*'
set @.strSQL = @.strSQL + ' and xactions.XACTIONCURRENCY = ''' +
@.strCurrency + ''' '

if @.strVFEID <> '*'
set @.strSQL = @.strSQL + ' and xactions.VFEID = ''' + @.strVFEID + ''' '

set @.strSQL = @.strSQL + ' ) where TheHour = ''' + @.numHour + ''' '

exec ( @.strSQL )

fetch next from MyHours into @.numHour

end -- while fetch

close MyHours
deallocate MyHours

select * from ##Averages order by TheHour

drop table ##Averages

/* end insert sp code here */

if (@.@.error <> 0)
begin
set @.strResult = 'Failure'
set @.strErrorDesc = 'Fail @. Step :' + @.strStep + ' Error : ' +
CONVERT(VARCHAR,@.@.Error)
return -1969
end
else
begin
set @.strResult = 'Success'
set @.strErrorDesc = ''
end

return 0

GOMany Thanks

I'll have a look at making those changes.

"Erland Sommarskog" <sommar@.algonet.se> wrote in message
news:Xns93E5F2C02272EYazorman@.127.0.0.1...
> Steve Thorpe (stephenthorpe@.nospam.hotmail.com) writes:
> > I am trying to write a report that calculates the average number of
> > sales over 7, 14, 31 and 365 days for each hourly period of the day.
> > the problem is it takes over 4 minutes to run.
>
> Troubleshooting performance problems over newsgroups is often difficult
> because, without access to the database it's not possible to test
> various scenarios. And without complete knowledge about the tables
> involved it is even more difficult. Just seeing the procedure code,
> may sometimes be sufficient, but not always.
> Anyway, I have two suggestions for your procedure, although none of
> them are likely to improve performance radically.
> The first is that you use a global temptable. Change this to a local
> temp table. This avoids problems if two users run this procedure
> simultaneously.
> The other is that you rewrite the procedure to not use dynamic SQL.
> As far as I can see, the only reason that you use dynamic SQL, is
> that you intended to have a comma-separated list in @.Wholesalers.
> I would suggest that you handle the list like this:
> CREATE TABLE #wholesalers (id int NOT NULL)
> INSERT #wholesalers (id)
> SELECT number FROM iter_intlist_to_table(@.wholesalers)
> You find the code for iter_intlist_to_table at
> http://www.algonet.se/~sommar/array...ist-of-integers.
> Armed with this temp table, you can, as far as I can see, rip out the
> dynamic SQL and replace it with static. This may give some performance
> benefit, but only some single second.
> However, once you have rewritten the code into static SQL, it will be
> more pleasant to take a look at it.
> It also helps if you post CREATE TABLE and CREATE INDEX statements
> for the involved table. Some hints about data sizes is also good.
>
> --
> Erland Sommarskog, SQL Server MVP, sommar@.algonet.se
> Books Online for SQL Server SP3 at
> http://www.microsoft.com/sql/techin.../2000/books.asp