Showing posts with label application. Show all posts
Showing posts with label application. Show all posts

Monday, March 26, 2012

Making outbound HTTP requests from SQLCLR

Hi,

I have written a C# console application that adds a message to a SB queue and a C# stored procedure that reads the message from the queue.

I have had so many problems that I'm beginning to doubt the usefulness of this, but that is probably just my frustration speaking.

I am stuck on putting an XML message into the queue and reading the XML in the stored procedure.

The console app has a simple object called Message. This class has 2 fields, a guid and a string. I serialize the object into XML using XmlSerializer. This results in an XML string that looks like this:

<?xml version="1.0" encoding="utf-16"?>
<Message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http:/
/www.w3.org/2001/XMLSchema">
<TranId>a5b4a32f-4940-46ea-a928-3aae33a067fe</TranId>
<Text>TEST</Text>
</Message>

I use a SqlCommand to SEND the message to the queue. I use the following code to SEND the message:

// Add dialog handle

SqlParameter paramDialogHandle = new SqlParameter("@.dh", SqlDbType.UniqueIdentifier);

paramDialogHandle.Value = this.DialogHandle;

cmd.Parameters.Add(paramDialogHandle);

// Add message

SqlParameter paramMsg = new SqlParameter("@.msg", SqlDbType.VarChar,4000);

paramMsg.Value = msg.ToXml();

cmd.Parameters.Add(paramMsg);

// Build the SEND command

cmd.CommandText = "SEND ON CONVERSATION @.dh " +

"MESSAGE TYPE [http://www.TestSB.com/msg/HelloWorld] " +

"(@.msg)";

cmd.ExecuteNonQuery();

For some reason, this message never gets to the stored procedure that is set up to be activated for this queue. Actually, it never even gets written to the queue.

However, If I change the type of parameter in the SEND above to SqlDbType.Xml, the message is written into the queue, but without the '<?xml version="1.0" encoding="utf-16"?>' beginning it, so when my stored procedure tries to deserialize the xml, using XmlSerializer, it fails.

Obviously, I have overcome the backflips needed to do XmlSerialization within the SQLCLR, and I am getting the stored procedure activated, because I do get a message logged showing the XML that is received.

Since I have the queue set up to only allow valid XML messages, I'm assuming that inclusion of the <? xml version..../> line prevents the message from passing Service Broker's XML validation. (And by the way, I have never seen an error message placed into the queue, the event log, or thrown when non-xml is passed to a queue that has XML validation turned on. The message just does not show up in the queue. Is this a bug?) But the lack of the line prevents XmlSerializer from working.

How the heck do you serialize an object into XML using XmlSerializer, so that it can be deserialized with XmlSerializer?

Thanks

]Monty[

On the Service Broker specific issues I advise you to try following the steps in this trubleshooting article I posted at http://blogs.msdn.com/remusrusanu/archive/2005/12/20/506221.aspx. What you will most likely find is that when it appears that you send the message and the message vanishes, you actualy gonna find an error message in the sender's service queue with the error complaining about the message being invalid XML formated.

You see, the XML validation of messages is always performed by the target service when the message is received, not by the sender when the message is sent. Therefore if you send an incorrect XML message, it will not trigger an error in the SEND statement. However, since I assume your message type is defined as WELL_FORMED_XML, the message will not pass the XML validation when is attempted to be enqueued in the target queue and an error message will be sent back. This is the error message you'll find in your sender's queue.

The XML formating problems you are seing are due to the parameter types you use. It makes a big difference on the XML if you pass it in as an VARCHAR(4000), an NVARCHAR(4000) or an XML datatype. VARCHAR types will support UTF-8 encoded XML, therefore your serializer needs to create UTF-8 XML. NVARCHAR type will support UTF-16 encoded, and you need to serialize it accordingly. I'm not an .Net XmlSerializer expert, but I believe you can specify the encoding to be used. I know for one that you can create an XmlTextWriter and specify the Encoding.UTF8 or Encoding.UTF16, then use this XmlTextWriter to obtain the xml stream from the XmlSerializer. Similarily, you can specify the encoding in the XmlTextReader when deserializing the XML.

However, if you use the XML datatype, then you shouldn't need to specify explicitly the encoding. It seems you got this working on the SEND side, but you cannot get the message body as an XML on the receive side. How do you obtain this message in the C# client in the receiver side? Are you using SqlCommand.ExecuteReader to parse the resultset of a RECEIVE statement? What you need to do is to make sure that you get back from the server an XML datatype, not an VARBINARY(MAX). Simply use a RECEIVE ... CAST(message_body AS XML) for this to happen.

HTH,
~ Remus

|||

Hi Remus,

Thanks for the reply. Yes, what you've posted about the data types was part of the problem. However, I have never been able to find any trace of a poorly formed XML error message, in the target's queue or in the initiator's queue. If you say so, I guess that's right, but it doesn't work for me.

I've gotten around the serialization problem by using nvarchar(max) on the send and receive side and the <? xml .../> is making it across fine now. However, now XmlSerializer is complaining about the first line of the XML that follows. I've given up on this and am in the process of simplifying things back down to were they were once somewhat working predictably.

My problem now is that I can only run my test once and get an error message, and then I must shut down Visual studio 2005 (because it is holding a connection open somewhere) Drop and then create the database in Sql Mgmt Studio, and then bring up VS2005 again and run my console application. If I run it 2 times in a row, the stored procedure stops getting activated, even though in my postdeployscript.sql, I am dropping and then recreating the activation of the newly installed stored proc using the following:

ALTER QUEUE [TestSB Queue] WITH ACTIVATION (DROP);

go

alter queue [TestSB Queue]

with status=on,

activation (

status = on,

procedure_name = ServiceProc,

max_queue_readers = 2,

execute as self);

That brings up another question: Why is it you must drop the activation and then create it again in order to get the activation to fire on the newly deployed stored procedure? I understand that the assembly containing the stored proc has a different version, but it took me forever to figure out that you had to do a drop first, and that the alter queue [xx] Activation(....) wasn't enough.

Anyway, I have been hitting my head against the wall with this for all week. Tomorrow I am going to start over with new solution and try to simplify things even more to get to the bottom of this. If you forced me to go into production right now with ServiceBroker, I'd have to complain that it isn't ready. Or I'm not ready at best. I've had so many flakey experiences so far, I know my confidence has been eroded. There is too little documentation and apparently not a lot of experience with C# programs written under Visual Studio that write to queues that are serviced by SQLCLR stored procedures. There is very little in the way of samples, etc. Heck the words 'postdeployscript' and 'predeplyscript', necessary things for doing SB stuff within VS, can't even be found in the Visual Studio help!

In the end, all I want to do is serialize a message through SB to some code that makes a web service call. Boy is that a tall order.

]Monty[

|||

Are you ending the sending dialog after the SEND? If that's the case, then when the error comes back it will find the dialog already ended and therefore it will simply delete the dialog, as well as the error message. If you do something like BEGIN DIALOG/SEND/END, this is similar to a 'fire and forget' scenario, where you (the sender) can never know if your message actually reached the target.

Anyway, using the Profiler can reveal a great deal of what's going on with the dialog messages, select the events in the Broker category.

Unfortunately I cannot help you too much with the CLR and Visual Studio deployment problems, since I'm unfamiliar with them myself. The dedicated .Net forum is monitored by experts with more knowledge in that area, http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=86&SiteID=1, it would worth the trouble to describe the problem there. There are also some blogs of experts in this area, like http://blogs.msdn.com/sqlclr/

One explanation for the weird behavior you see would be is your activated procedure never returns. You can verify this in the Profiler (the activation started/stopped events) as well as by querying the sys.dm_broker_activated_tasks view.

HTH,
~ Remus

|||

1. You do not have to ALTER QUEUE in order to use the newly installed stored proc. If there are any instances of the stored proc already running, they will continue to run the old version. However, the next time Service Broker activates a new proc it should automatically launch the newly deployed version. This behavior is exactly the same as that of SQL when ALTER PROCEDURE can update the procedure without killing spids that are already running the older version. However, any new invocation will use the new code.

2. You should be able to close the connection to the database from Visual Studio by opening the Server Explorer pane, navigating to the database, right clicking and selecting 'Close Connection'.

3. You do not have to DROP activation before reconfiguring it. You can adjust any/all of the settings of activation (viz, status, procedure_name, max_queue_readers and execute as user) using a single ALTER QUEUE statement.

4. Here's a resource on XmlSerialization in SQLCLR:
http://blogs.msdn.com/sqlclr/archive/2005/07/25/Vineet.aspx

The steps I perform are as follows:
SqlCommand cmd = conn.CreateCommand()
cmd.CommandText = @."WAITFOR (RECEIVE TOP(1) message_body, ..., FROM [YourQueue]), TIMEOUT 5000";
cmd.Transaction = tran;
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
SqlBytes body = reader.GetSqlBytes();
// XmlSerializer xs;
YourObject yo = (YourObject) xs.Deserialize(body.Stream);
//...
}

5. If you install the samples that come with the SQL Server DVDs, you should find a HelloWorld_CLR sample as well as a ServiceBrokerInterface library which is a sample programming model for writing service broker application. The library also has a shopping cart sample.

|||

I just wanted to caution you about using SQLCLR to make outbound HTTP requests. When you make a web request, note that you are doing so as the user running sqlservr.exe. If this is a machine account, you may want to think about the consequences of that principle making outbound HTTP connections to proxy servers (or worse the destination web server itself).

Secondly, if you make a blocking web request call, you will be holding the transaction locks on the conversation group (and anything else that the stored proc may have locked) until the response is received and parsed.

Thirdly, you are using up one of sqlservr's threads for doing the web request, preventing the server from doing real database work until the request returns.

Finally, how are you going to handle errors from the webserver? Either you will have to rollback the transaction (but then the message will pop up again on executing a RECEIVE) or use some sophisticated mechanism of logging pending requests and retrying them using some retry logic. If you chose to rollback, remember that rolling back 5 times consecutively will disable the queue to prevent the poisoned message from repeatedly activating the queue.

If any of these issues concern you then you might want to think about re-architecting the solution to use an external ADO.NET app that receives the messages rather than an internally activated stored proc. If you want the ADO.NET app to be dynamically launched you could try the external activator mentioned here (http://rushi.desai.name/Blog/tabid/54/EntryID/7/Default.aspx).

|||

Hi guys,

Thanks for the replies. This is really going somewhere now :)

1) Getting errors when sending non-xml thru a 'well formed xml' queue:
Yes, I am ending the dialog after the send. Are you saying that I need to turn around and wait for a response error message when the messsage is read? If so, how do I keep the transaction from becoming a super long one? That's one of the points I'm trying to make. This is a fire and forget queue. I'm basically trying to do a one-way message. I think the 'well-formed-xml' validation is not to useful in this case. I can't wait around for the reading of the message to generate a returning error message, that might be in an hour or so from now, and the transaction will have to be open all that time. I think a better approach is to turn off the validation and deal with it in the application code.

2) Doing an ALTER QUEUE after a new stored procedure is installed.
Interesting theory. Unfortunately, I have *NEVER* been able to get the stored procedure to fire after a deploy from visual studio. I spent 2 days on this until I tried doing a drop and create on the activation and finally got the stored procedure to be called. I'm obviously doing something wrong, but I can't for the life of me figure out what it is. And it only works for me if I do the drop and then the create. The create is not enough for me.

3) Making outbound HTTP requests from SQLCLR
Well, reliable messaging is the whole point of my exercise. There is no Indigo yet and QueuedComponents/MSMQ is not supported officially by Microsoft in a clustered environment, and a clustered environment is required for fault tolerance in production since there is no disaster recovery for MSMQ. Believe me, I have been there. QueuedComponents/MSMQ is not an option. So I'm left with SB queues with stored procedures making web service calls. I understand the transacional concerns that have been raised, and handling errors is a big unsolved problem because of the poison message 'feature' (can it be turned off?), and the fact that there is no way to delay a message from being received again, and the fact that the stored procedure is supposed to read all the messages before it stops. Assuming the web server is down, if I requeue the message back to the queue again, the stored procedure will just keep reading the same message over and over. I really don't know how to handle errors when the web service call fails, I haven't been able to get that far yet.Are you saying that internal activation is not the way to do this, and external activation is the way to go? Does it help with handling errors or just avoid the resource usage problem of http request inside of SQLCLR?

4) Closing connections to the database by closing the connections in server explorer.
I do this but Visual studio is still holding a connection, because I can't drop the database unless I close VS. Even closing the solution doesn't work. If I didn't have the activation problem, I wouldn't have to go through this step, so solving the activation problem would lessen this problem a bunch.

Thanks
]Monty[

EDIT: I was just checking out the external activation samples, but it uses that ServiceBroker Interface code. So the example only really shows how to use it, rather than how to do external activation. Are there any simplified examples available that don't use the interface code? I'm sorry but that code is not commented very well and is very complicated. I guess if that is all there is available then I can try to make it out, but I started my current excerise using it, and eventually gutted it down to the basic parts trying to understand it and I've obviously messed it up.

|||

Hi again,

On the subject of the external activation sample:

Imagine that the environment is a classic 3 tier architecture, a UI or Web Service layer, an application layer that the UI talks to through web services, (the UI and the app layer are web farms not clustered using the clustering service but clustered with nlb) and finally the database server layer. How is a Windows Service going to be safely running in this environment? I need a clustered Windows Service layer in order to provide fault tolerance for the windows service. It doesn't exist. Do I run a copy of the service on each web service machine in the app layer? How do I get them all to coordinate? Does the sample provided have this support?

]Monty[

|||

Monty Hi,

I'm really glad you're making progress. I'm sure we'll nail this down in no time.

But first of all, you are making some wrong assumtions about how Service Broker works and on how to write Service Broker apps. Service Broker messages will not be sent until a transaction commits. So definetely there will be no long transaction left open waiting for the error, since the error by definition won't come until you commit your transaction :). The model is like this: you send the message and commit. Then the application goes about it's normal business. Later (as you pointed out, it may be hours later), either an error comes back (mallformed XML), either the dialog times out (this is just another error message in your queue), either a response comes back. This message (errors are also messages) should be the trigger to continue your processing on this request (continue from where the SEND left). You can either use activation on the sender's side, or the application can have a dedicated listener thread that sits in a WAITFOR(RECEIVE...) loop. In the later case, the application should be, of course, prepared to deal with the case when it just started up and will find response messages for requests it made a week ago, the last time it was running.

BTW, in case you noticed that Service Broker messages appear to be sent immeadetly, before the transaction is commited, this is just an optimization we do in the case when the target service resides in the same instance as the sender. The 'sent' messages are actually locked by the sender's transaction and won't be available for RECEIVE in any other transaction until the sender's commit. And if the optimization cannot be performed for whatever reason (target database offline, target queue disabled, target conversation locked etc), the message will take the normal path (through sender's sys.transmission_queue).

Now about the WebService calls.

The HTTP requests per say are very expensive to be done from inside SQL Server. So it is a matter of resource consumtion to be external, not internal.

On how to handle a message like this (that requires a potential failure in an expensive operation, like a WS call), my proposed handling is this:

begin transaction
receive message
if message is web request
save state of request (http address, caller etc)
else is message is retry timer message
load state of request
endif
save a retry timer on the dialog (say 1 minute) using BEGIN DIALOG TIMER
commit
do the web request (no transaction open)
if success
begin transaction
reset retry timer
send back response
end conversation
commit
endif

This way you don't held long transaction (nothing is worse to a database than those!) and you have a persistent retry timer, stored in the database. You will retry your web request even after a server restart or a failover (cluster or mirroring), because dialog timers are persisted. And you don't rollback in case of web call failure.

HTH,
~ Remus

|||

Remus Rusanu wrote:

But first of all, you are making some wrong assumtions about how Service Broker works and on how to write Service Broker apps. Service Broker messages will not be sent until a transaction commits. So definetely there will be no long transaction left open waiting for the error, since the error by definition won't come until you commit your transaction :). The model is like this: you send the message and commit. Then the application goes about it's normal business. Later (as you pointed out, it may be hours later), either an error comes back (mallformed XML), either the dialog times out (this is just another error message in your queue), either a response comes back. This message (errors are also messages) should be the trigger to continue your processing on this request (continue from where the SEND left). You can either use activation on the sender's side, or the application can have a dedicated listener thread that sits in a WAITFOR(RECEIVE...) loop. In the later case, the application should be, of course, prepared to deal with the case when it just started up and will find response messages for requests it made a week ago, the last time it was running.

Hi Remus

You hit the nail on the head, I am completely confused on how this works. I thought that was pretty obvious from my previous posts. :)

So to summarize, when I send a message, I do the SEND, and commit the transaction, but I don't END CONVERSATION until I get back a response or an error. 1) I'm not sending back a response on the receive side, and 2) I'm ending the conversation as soon as the send completes. Also, since my sender is a console application, I should turn around and wait for the response/errors, before sending another message, correct?

TIA

]Monty[

|||

Hi again,

Another question?

After sending the message (and not ending the conversation), do I receive on the queue I did the send on or the client queue that I had to set up to create the initiator service?

Here's the ddl for the queues, messages, and contracts:

PRINT 'create message SBTest.Message1';

CREATE MESSAGE TYPE

[SBTest.Message1]

validation = NONE;

PRINT 'create contract SBTest.Contract';

CREATE CONTRACT [SBTest.Contract]

(

[SBTest.Message1] SENT BY INITIATOR

);

go

--*********************************************

--* Create the [SBTest] service

--*********************************************

PRINT 'create queue ''[SBTest Queue]''';

CREATE QUEUE [SBTest Queue];

PRINT 'create service ''[SBTest]''';

CREATE SERVICE [SBTest]

ON QUEUE [SBTest Queue]

(

[SBTest.Contract]

);

go

--*********************************************

--* Create the [SBTest Client] service (the client.exe program)

--*********************************************

PRINT 'create queue ''[SBTest Client Queue]''';

CREATE QUEUE [SBTest Client Queue];

PRINT 'create service ''[SBTest Client]''';

CREATE SERVICE [SBTest Client]

on queue [SBTest Client Queue];

-- no contract because it only initiates messages

go

Do I do a recieve on [SBTest Queue] or [SBTest Client Queue]?

TIA

]Monty[

|||

Response messages will be sent by the target service to the initiator service. Hence they will be delivered to the initiator queue and you should receive them from there (i.e. [SBTest Client Queue]) in your case. If you want the response message to actually contain a real message body, you will need to add a new message type and alter the contract. If your responses do not contain any info but simply acknowledge the initiator that its request has been handled, you could simply end the conversation on the target which will send the special 'End Conversation' message back to the initiator as follows:
Initiator Target


Begin Tran
Begin Dialog
Send a request
Commit
Begin Tran
Receive
Process message
End conversation
Commit
Begin Tran
Receive
If 'End Dialog' message
End conversation
Else If 'Error' message
Log/MsgBox/Email
End conversation
Commit

As Remus explained handling the responses could be performed in a background thread of your console application. If you need the user to be alerted of errored dialogs immediately, this background thread could signal the UI thread to pop up a message box. Or it could simply the log the failures to a table so that the user can look at the table to see what failed later. If you don't need the responses to be processed immediately, you could setup a periodic task (you can do that using SSB itself without requiring SQL Agent) that processes the responses.

|||

Monty Shaw writes:

Also, since my sender is a console application, I should turn around and wait for the response/errors, before sending another message, correct?

This depends on whether the user need to block and wait for the response before submitting the next request. But as you said, the user is not really interested in the response and hence you could simply keep accepting new requests on the console and then submit them using "Begin Dialog/Send" in a transaction. Processing of responses can be performed asynchronously in a background task or deferred to a batched task that runs every night.

Later,
Rushi

|||

Ok guys,

I created a small visual studio solution that does things the way you've suggested. I've zipped up the entire solution. I can not get the stored procedure to activate and consume messages out of the queue.

In order to recreate what I am seeing, you will have to:

1. unzip this zip

2. change the databse references in the Database project and the SqlServer project.

3. run the create.sql script to create the database.

4. deploy the solution

5. run the activate.sql script to set up the activation of the stored procedure

6. run the Client.exe (run without debug).

The first time you run this it may work. If so run it again. What I see after the first run, and a solution deploy, is that the stored procedure never again is activated to process messages. The stored proc is set up to just read the messages and then end the conversation along with writing messages into the log table. Nothing, nada.

Help!

Is there a way to upload a zip file? I wrote the above thinking I could attach a file to this post, but there doesn't appear to be a way to do that. If you can tell me how to do that or where to send it, I have a zip file just waiting.

]Monty[

|||

You should wait for a response on [SBTest Client Queue].

The [SBTest] should end the conversation on success. The client will get back an error message on failure (for whatever reason: XML validation, conversation timeout, access denied on target service) or an end conversation message on case of success. The client could wait for a response with a WAITFOR(RECEIVE ... FROM [SbTest Client Queue] WHERE CONVERSATION_HANDLE = @.conversation_handle) where @.conversation_handle is the handle returned by BEGIN DIALOG.

BTW, if the initiator (sender) is an console application and there is no message sent back to the initiator, I'm not sure it makes sense for the console application to wait for a response, but I guess this is solely for the purpose of testing and figuring out how things work.

HTH,
~ Remus

Making outbound HTTP requests from SQLCLR

Hi,

I have written a C# console application that adds a message to a SB queue and a C# stored procedure that reads the message from the queue.

I have had so many problems that I'm beginning to doubt the usefulness of this, but that is probably just my frustration speaking.

I am stuck on putting an XML message into the queue and reading the XML in the stored procedure.

The console app has a simple object called Message. This class has 2 fields, a guid and a string. I serialize the object into XML using XmlSerializer. This results in an XML string that looks like this:

<?xml version="1.0" encoding="utf-16"?>
<Message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http:/
/www.w3.org/2001/XMLSchema">
<TranId>a5b4a32f-4940-46ea-a928-3aae33a067fe</TranId>
<Text>TEST</Text>
</Message>

I use a SqlCommand to SEND the message to the queue. I use the following code to SEND the message:

// Add dialog handle

SqlParameter paramDialogHandle = new SqlParameter("@.dh", SqlDbType.UniqueIdentifier);

paramDialogHandle.Value = this.DialogHandle;

cmd.Parameters.Add(paramDialogHandle);

// Add message

SqlParameter paramMsg = new SqlParameter("@.msg", SqlDbType.VarChar,4000);

paramMsg.Value = msg.ToXml();

cmd.Parameters.Add(paramMsg);

// Build the SEND command

cmd.CommandText = "SEND ON CONVERSATION @.dh " +

"MESSAGE TYPE [http://www.TestSB.com/msg/HelloWorld] " +

"(@.msg)";

cmd.ExecuteNonQuery();

For some reason, this message never gets to the stored procedure that is set up to be activated for this queue. Actually, it never even gets written to the queue.

However, If I change the type of parameter in the SEND above to SqlDbType.Xml, the message is written into the queue, but without the '<?xml version="1.0" encoding="utf-16"?>' beginning it, so when my stored procedure tries to deserialize the xml, using XmlSerializer, it fails.

Obviously, I have overcome the backflips needed to do XmlSerialization within the SQLCLR, and I am getting the stored procedure activated, because I do get a message logged showing the XML that is received.

Since I have the queue set up to only allow valid XML messages, I'm assuming that inclusion of the <? xml version..../> line prevents the message from passing Service Broker's XML validation. (And by the way, I have never seen an error message placed into the queue, the event log, or thrown when non-xml is passed to a queue that has XML validation turned on. The message just does not show up in the queue. Is this a bug?) But the lack of the line prevents XmlSerializer from working.

How the heck do you serialize an object into XML using XmlSerializer, so that it can be deserialized with XmlSerializer?

Thanks

]Monty[

On the Service Broker specific issues I advise you to try following the steps in this trubleshooting article I posted at http://blogs.msdn.com/remusrusanu/archive/2005/12/20/506221.aspx. What you will most likely find is that when it appears that you send the message and the message vanishes, you actualy gonna find an error message in the sender's service queue with the error complaining about the message being invalid XML formated.

You see, the XML validation of messages is always performed by the target service when the message is received, not by the sender when the message is sent. Therefore if you send an incorrect XML message, it will not trigger an error in the SEND statement. However, since I assume your message type is defined as WELL_FORMED_XML, the message will not pass the XML validation when is attempted to be enqueued in the target queue and an error message will be sent back. This is the error message you'll find in your sender's queue.

The XML formating problems you are seing are due to the parameter types you use. It makes a big difference on the XML if you pass it in as an VARCHAR(4000), an NVARCHAR(4000) or an XML datatype. VARCHAR types will support UTF-8 encoded XML, therefore your serializer needs to create UTF-8 XML. NVARCHAR type will support UTF-16 encoded, and you need to serialize it accordingly. I'm not an .Net XmlSerializer expert, but I believe you can specify the encoding to be used. I know for one that you can create an XmlTextWriter and specify the Encoding.UTF8 or Encoding.UTF16, then use this XmlTextWriter to obtain the xml stream from the XmlSerializer. Similarily, you can specify the encoding in the XmlTextReader when deserializing the XML.

However, if you use the XML datatype, then you shouldn't need to specify explicitly the encoding. It seems you got this working on the SEND side, but you cannot get the message body as an XML on the receive side. How do you obtain this message in the C# client in the receiver side? Are you using SqlCommand.ExecuteReader to parse the resultset of a RECEIVE statement? What you need to do is to make sure that you get back from the server an XML datatype, not an VARBINARY(MAX). Simply use a RECEIVE ... CAST(message_body AS XML) for this to happen.

HTH,
~ Remus

|||

Hi Remus,

Thanks for the reply. Yes, what you've posted about the data types was part of the problem. However, I have never been able to find any trace of a poorly formed XML error message, in the target's queue or in the initiator's queue. If you say so, I guess that's right, but it doesn't work for me.

I've gotten around the serialization problem by using nvarchar(max) on the send and receive side and the <? xml .../> is making it across fine now. However, now XmlSerializer is complaining about the first line of the XML that follows. I've given up on this and am in the process of simplifying things back down to were they were once somewhat working predictably.

My problem now is that I can only run my test once and get an error message, and then I must shut down Visual studio 2005 (because it is holding a connection open somewhere) Drop and then create the database in Sql Mgmt Studio, and then bring up VS2005 again and run my console application. If I run it 2 times in a row, the stored procedure stops getting activated, even though in my postdeployscript.sql, I am dropping and then recreating the activation of the newly installed stored proc using the following:

ALTER QUEUE [TestSB Queue] WITH ACTIVATION (DROP);

go

alter queue [TestSB Queue]

with status=on,

activation (

status = on,

procedure_name = ServiceProc,

max_queue_readers = 2,

execute as self);

That brings up another question: Why is it you must drop the activation and then create it again in order to get the activation to fire on the newly deployed stored procedure? I understand that the assembly containing the stored proc has a different version, but it took me forever to figure out that you had to do a drop first, and that the alter queue [xx] Activation(....) wasn't enough.

Anyway, I have been hitting my head against the wall with this for all week. Tomorrow I am going to start over with new solution and try to simplify things even more to get to the bottom of this. If you forced me to go into production right now with ServiceBroker, I'd have to complain that it isn't ready. Or I'm not ready at best. I've had so many flakey experiences so far, I know my confidence has been eroded. There is too little documentation and apparently not a lot of experience with C# programs written under Visual Studio that write to queues that are serviced by SQLCLR stored procedures. There is very little in the way of samples, etc. Heck the words 'postdeployscript' and 'predeplyscript', necessary things for doing SB stuff within VS, can't even be found in the Visual Studio help!

In the end, all I want to do is serialize a message through SB to some code that makes a web service call. Boy is that a tall order.

]Monty[

|||

Are you ending the sending dialog after the SEND? If that's the case, then when the error comes back it will find the dialog already ended and therefore it will simply delete the dialog, as well as the error message. If you do something like BEGIN DIALOG/SEND/END, this is similar to a 'fire and forget' scenario, where you (the sender) can never know if your message actually reached the target.

Anyway, using the Profiler can reveal a great deal of what's going on with the dialog messages, select the events in the Broker category.

Unfortunately I cannot help you too much with the CLR and Visual Studio deployment problems, since I'm unfamiliar with them myself. The dedicated .Net forum is monitored by experts with more knowledge in that area, http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=86&SiteID=1, it would worth the trouble to describe the problem there. There are also some blogs of experts in this area, like http://blogs.msdn.com/sqlclr/

One explanation for the weird behavior you see would be is your activated procedure never returns. You can verify this in the Profiler (the activation started/stopped events) as well as by querying the sys.dm_broker_activated_tasks view.

HTH,
~ Remus

|||

1. You do not have to ALTER QUEUE in order to use the newly installed stored proc. If there are any instances of the stored proc already running, they will continue to run the old version. However, the next time Service Broker activates a new proc it should automatically launch the newly deployed version. This behavior is exactly the same as that of SQL when ALTER PROCEDURE can update the procedure without killing spids that are already running the older version. However, any new invocation will use the new code.

2. You should be able to close the connection to the database from Visual Studio by opening the Server Explorer pane, navigating to the database, right clicking and selecting 'Close Connection'.

3. You do not have to DROP activation before reconfiguring it. You can adjust any/all of the settings of activation (viz, status, procedure_name, max_queue_readers and execute as user) using a single ALTER QUEUE statement.

4. Here's a resource on XmlSerialization in SQLCLR:
http://blogs.msdn.com/sqlclr/archive/2005/07/25/Vineet.aspx

The steps I perform are as follows:
SqlCommand cmd = conn.CreateCommand()
cmd.CommandText = @."WAITFOR (RECEIVE TOP(1) message_body, ..., FROM [YourQueue]), TIMEOUT 5000";
cmd.Transaction = tran;
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
SqlBytes body = reader.GetSqlBytes();
// XmlSerializer xs;
YourObject yo = (YourObject) xs.Deserialize(body.Stream);
//...
}

5. If you install the samples that come with the SQL Server DVDs, you should find a HelloWorld_CLR sample as well as a ServiceBrokerInterface library which is a sample programming model for writing service broker application. The library also has a shopping cart sample.

|||

I just wanted to caution you about using SQLCLR to make outbound HTTP requests. When you make a web request, note that you are doing so as the user running sqlservr.exe. If this is a machine account, you may want to think about the consequences of that principle making outbound HTTP connections to proxy servers (or worse the destination web server itself).

Secondly, if you make a blocking web request call, you will be holding the transaction locks on the conversation group (and anything else that the stored proc may have locked) until the response is received and parsed.

Thirdly, you are using up one of sqlservr's threads for doing the web request, preventing the server from doing real database work until the request returns.

Finally, how are you going to handle errors from the webserver? Either you will have to rollback the transaction (but then the message will pop up again on executing a RECEIVE) or use some sophisticated mechanism of logging pending requests and retrying them using some retry logic. If you chose to rollback, remember that rolling back 5 times consecutively will disable the queue to prevent the poisoned message from repeatedly activating the queue.

If any of these issues concern you then you might want to think about re-architecting the solution to use an external ADO.NET app that receives the messages rather than an internally activated stored proc. If you want the ADO.NET app to be dynamically launched you could try the external activator mentioned here (http://rushi.desai.name/Blog/tabid/54/EntryID/7/Default.aspx).

|||

Hi guys,

Thanks for the replies. This is really going somewhere now :)

1) Getting errors when sending non-xml thru a 'well formed xml' queue:
Yes, I am ending the dialog after the send. Are you saying that I need to turn around and wait for a response error message when the messsage is read? If so, how do I keep the transaction from becoming a super long one? That's one of the points I'm trying to make. This is a fire and forget queue. I'm basically trying to do a one-way message. I think the 'well-formed-xml' validation is not to useful in this case. I can't wait around for the reading of the message to generate a returning error message, that might be in an hour or so from now, and the transaction will have to be open all that time. I think a better approach is to turn off the validation and deal with it in the application code.

2) Doing an ALTER QUEUE after a new stored procedure is installed.
Interesting theory. Unfortunately, I have *NEVER* been able to get the stored procedure to fire after a deploy from visual studio. I spent 2 days on this until I tried doing a drop and create on the activation and finally got the stored procedure to be called. I'm obviously doing something wrong, but I can't for the life of me figure out what it is. And it only works for me if I do the drop and then the create. The create is not enough for me.

3) Making outbound HTTP requests from SQLCLR
Well, reliable messaging is the whole point of my exercise. There is no Indigo yet and QueuedComponents/MSMQ is not supported officially by Microsoft in a clustered environment, and a clustered environment is required for fault tolerance in production since there is no disaster recovery for MSMQ. Believe me, I have been there. QueuedComponents/MSMQ is not an option. So I'm left with SB queues with stored procedures making web service calls. I understand the transacional concerns that have been raised, and handling errors is a big unsolved problem because of the poison message 'feature' (can it be turned off?), and the fact that there is no way to delay a message from being received again, and the fact that the stored procedure is supposed to read all the messages before it stops. Assuming the web server is down, if I requeue the message back to the queue again, the stored procedure will just keep reading the same message over and over. I really don't know how to handle errors when the web service call fails, I haven't been able to get that far yet.Are you saying that internal activation is not the way to do this, and external activation is the way to go? Does it help with handling errors or just avoid the resource usage problem of http request inside of SQLCLR?

4) Closing connections to the database by closing the connections in server explorer.
I do this but Visual studio is still holding a connection, because I can't drop the database unless I close VS. Even closing the solution doesn't work. If I didn't have the activation problem, I wouldn't have to go through this step, so solving the activation problem would lessen this problem a bunch.

Thanks
]Monty[

EDIT: I was just checking out the external activation samples, but it uses that ServiceBroker Interface code. So the example only really shows how to use it, rather than how to do external activation. Are there any simplified examples available that don't use the interface code? I'm sorry but that code is not commented very well and is very complicated. I guess if that is all there is available then I can try to make it out, but I started my current excerise using it, and eventually gutted it down to the basic parts trying to understand it and I've obviously messed it up.

|||

Hi again,

On the subject of the external activation sample:

Imagine that the environment is a classic 3 tier architecture, a UI or Web Service layer, an application layer that the UI talks to through web services, (the UI and the app layer are web farms not clustered using the clustering service but clustered with nlb) and finally the database server layer. How is a Windows Service going to be safely running in this environment? I need a clustered Windows Service layer in order to provide fault tolerance for the windows service. It doesn't exist. Do I run a copy of the service on each web service machine in the app layer? How do I get them all to coordinate? Does the sample provided have this support?

]Monty[

|||

Monty Hi,

I'm really glad you're making progress. I'm sure we'll nail this down in no time.

But first of all, you are making some wrong assumtions about how Service Broker works and on how to write Service Broker apps. Service Broker messages will not be sent until a transaction commits. So definetely there will be no long transaction left open waiting for the error, since the error by definition won't come until you commit your transaction :). The model is like this: you send the message and commit. Then the application goes about it's normal business. Later (as you pointed out, it may be hours later), either an error comes back (mallformed XML), either the dialog times out (this is just another error message in your queue), either a response comes back. This message (errors are also messages) should be the trigger to continue your processing on this request (continue from where the SEND left). You can either use activation on the sender's side, or the application can have a dedicated listener thread that sits in a WAITFOR(RECEIVE...) loop. In the later case, the application should be, of course, prepared to deal with the case when it just started up and will find response messages for requests it made a week ago, the last time it was running.

BTW, in case you noticed that Service Broker messages appear to be sent immeadetly, before the transaction is commited, this is just an optimization we do in the case when the target service resides in the same instance as the sender. The 'sent' messages are actually locked by the sender's transaction and won't be available for RECEIVE in any other transaction until the sender's commit. And if the optimization cannot be performed for whatever reason (target database offline, target queue disabled, target conversation locked etc), the message will take the normal path (through sender's sys.transmission_queue).

Now about the WebService calls.

The HTTP requests per say are very expensive to be done from inside SQL Server. So it is a matter of resource consumtion to be external, not internal.

On how to handle a message like this (that requires a potential failure in an expensive operation, like a WS call), my proposed handling is this:

begin transaction
receive message
if message is web request
save state of request (http address, caller etc)
else is message is retry timer message
load state of request
endif
save a retry timer on the dialog (say 1 minute) using BEGIN DIALOG TIMER
commit
do the web request (no transaction open)
if success
begin transaction
reset retry timer
send back response
end conversation
commit
endif

This way you don't held long transaction (nothing is worse to a database than those!) and you have a persistent retry timer, stored in the database. You will retry your web request even after a server restart or a failover (cluster or mirroring), because dialog timers are persisted. And you don't rollback in case of web call failure.

HTH,
~ Remus

|||

Remus Rusanu wrote:

But first of all, you are making some wrong assumtions about how Service Broker works and on how to write Service Broker apps. Service Broker messages will not be sent until a transaction commits. So definetely there will be no long transaction left open waiting for the error, since the error by definition won't come until you commit your transaction :). The model is like this: you send the message and commit. Then the application goes about it's normal business. Later (as you pointed out, it may be hours later), either an error comes back (mallformed XML), either the dialog times out (this is just another error message in your queue), either a response comes back. This message (errors are also messages) should be the trigger to continue your processing on this request (continue from where the SEND left). You can either use activation on the sender's side, or the application can have a dedicated listener thread that sits in a WAITFOR(RECEIVE...) loop. In the later case, the application should be, of course, prepared to deal with the case when it just started up and will find response messages for requests it made a week ago, the last time it was running.

Hi Remus

You hit the nail on the head, I am completely confused on how this works. I thought that was pretty obvious from my previous posts. :)

So to summarize, when I send a message, I do the SEND, and commit the transaction, but I don't END CONVERSATION until I get back a response or an error. 1) I'm not sending back a response on the receive side, and 2) I'm ending the conversation as soon as the send completes. Also, since my sender is a console application, I should turn around and wait for the response/errors, before sending another message, correct?

TIA

]Monty[

|||

Hi again,

Another question?

After sending the message (and not ending the conversation), do I receive on the queue I did the send on or the client queue that I had to set up to create the initiator service?

Here's the ddl for the queues, messages, and contracts:

PRINT 'create message SBTest.Message1';

CREATE MESSAGE TYPE

[SBTest.Message1]

validation = NONE;

PRINT 'create contract SBTest.Contract';

CREATE CONTRACT [SBTest.Contract]

(

[SBTest.Message1] SENT BY INITIATOR

);

go

--*********************************************

--* Create the [SBTest] service

--*********************************************

PRINT 'create queue ''[SBTest Queue]''';

CREATE QUEUE [SBTest Queue];

PRINT 'create service ''[SBTest]''';

CREATE SERVICE [SBTest]

ON QUEUE [SBTest Queue]

(

[SBTest.Contract]

);

go

--*********************************************

--* Create the [SBTest Client] service (the client.exe program)

--*********************************************

PRINT 'create queue ''[SBTest Client Queue]''';

CREATE QUEUE [SBTest Client Queue];

PRINT 'create service ''[SBTest Client]''';

CREATE SERVICE [SBTest Client]

on queue [SBTest Client Queue];

-- no contract because it only initiates messages

go

Do I do a recieve on [SBTest Queue] or [SBTest Client Queue]?

TIA

]Monty[

|||

Response messages will be sent by the target service to the initiator service. Hence they will be delivered to the initiator queue and you should receive them from there (i.e. [SBTest Client Queue]) in your case. If you want the response message to actually contain a real message body, you will need to add a new message type and alter the contract. If your responses do not contain any info but simply acknowledge the initiator that its request has been handled, you could simply end the conversation on the target which will send the special 'End Conversation' message back to the initiator as follows:
Initiator Target


Begin Tran
Begin Dialog
Send a request
Commit
Begin Tran
Receive
Process message
End conversation
Commit
Begin Tran
Receive
If 'End Dialog' message
End conversation
Else If 'Error' message
Log/MsgBox/Email
End conversation
Commit

As Remus explained handling the responses could be performed in a background thread of your console application. If you need the user to be alerted of errored dialogs immediately, this background thread could signal the UI thread to pop up a message box. Or it could simply the log the failures to a table so that the user can look at the table to see what failed later. If you don't need the responses to be processed immediately, you could setup a periodic task (you can do that using SSB itself without requiring SQL Agent) that processes the responses.

|||

Monty Shaw writes:

Also, since my sender is a console application, I should turn around and wait for the response/errors, before sending another message, correct?

This depends on whether the user need to block and wait for the response before submitting the next request. But as you said, the user is not really interested in the response and hence you could simply keep accepting new requests on the console and then submit them using "Begin Dialog/Send" in a transaction. Processing of responses can be performed asynchronously in a background task or deferred to a batched task that runs every night.

Later,
Rushi

|||

Ok guys,

I created a small visual studio solution that does things the way you've suggested. I've zipped up the entire solution. I can not get the stored procedure to activate and consume messages out of the queue.

In order to recreate what I am seeing, you will have to:

1. unzip this zip

2. change the databse references in the Database project and the SqlServer project.

3. run the create.sql script to create the database.

4. deploy the solution

5. run the activate.sql script to set up the activation of the stored procedure

6. run the Client.exe (run without debug).

The first time you run this it may work. If so run it again. What I see after the first run, and a solution deploy, is that the stored procedure never again is activated to process messages. The stored proc is set up to just read the messages and then end the conversation along with writing messages into the log table. Nothing, nada.

Help!

Is there a way to upload a zip file? I wrote the above thinking I could attach a file to this post, but there doesn't appear to be a way to do that. If you can tell me how to do that or where to send it, I have a zip file just waiting.

]Monty[

|||

You should wait for a response on [SBTest Client Queue].

The [SBTest] should end the conversation on success. The client will get back an error message on failure (for whatever reason: XML validation, conversation timeout, access denied on target service) or an end conversation message on case of success. The client could wait for a response with a WAITFOR(RECEIVE ... FROM [SbTest Client Queue] WHERE CONVERSATION_HANDLE = @.conversation_handle) where @.conversation_handle is the handle returned by BEGIN DIALOG.

BTW, if the initiator (sender) is an console application and there is no message sent back to the initiator, I'm not sure it makes sense for the console application to wait for a response, but I guess this is solely for the purpose of testing and figuring out how things work.

HTH,
~ Remus

Making our SQL Server 2000 application ready for SQL Server 2005

We have several applications that were developed using SQL Server 2000. Most of our customers run MSDE, some the full SQL Server 2000. We are in the process of making sure our applications will work properly in SQL Server 2005 / SQL Express.

I have a few questions regarding this issue:-

1. Should I set the compatibility level to 80 for our databases or should I aim to make our applications work the 90 compatibility level?

I've run the Upgrade Advisor against our databases and this has not flagged up any issues. Does this mean the databases are compliant with the 90 compatibility level.

Of course this hasn't verified the queries built into my VB application so presumably I need to test our applications thoroughly before we let our customers run them on SQL Server 2005? (Note: Our newest applications do approx. 95% of the queries through stored procedures, however our older applications are more like 50% - this I presume potentially means there are a lot of queries hard coded into our code that could potentially not work and we need to test the applications directly against SQL Server 2005?)

2. If the compatibility level is set to 80, does the guarantee the database functions EXACTLY the same as SQL Server 2000? Could anything not work that did work in SQL Server 2000? Note: I know the SQL Agent Service is not available in SQL Express - this is not my main concern - i'm more on about general stuff like queries etc here.

3. If the compatibility level is set to 80 do you still get some SQL Server 2005 benefits - e.g. running on a faster engine giving me performance benefits or does the database need to be set to compatibility level 90 to receive any performance benefits?

4. If you restore a SQL Server 2000 database into SQL Server 2005, does it automatically update the database so it no longer will work in SQL Server 2000? Can I for instance have the database set to compatibility level 80 with nothing upgraded and then restore the database back on a SQL Server 2000 machine. I don't believe this is possible, but need to check.
Thanks in advance,
Chris

1 The upgrade advisor checks that your SQL server config is okay for upgrade, not the database itself;
Analysis Services Upgrade Issues|||

Mulhall wrote:

2&3 Check out this link and "Behavioral Differences Between Earlier Compatibility Levels and Level 90"
http://msdn2.microsoft.com/en-us/library/ms178653.aspx

In this link it states..

"The sp_dbcmptlevel stored procedure affects behaviors only for the specified database, not for the entire server. sp_dbcmptlevel provides only partial backward compatibility with earlier versions of SQL Server. Use sp_dbcmptlevel as an interim migration aid to work around version differences in the behaviors that are controlled by the relevant compatibility level setting. If existing SQL Server applications are affected by behavioral differences in SQL Server 2005, convert the application to work properly. Then use sp_dbcmptlevel to change the compatibility level to 90."

The above text implies compatibility levels should be used just as an aid until our application is fixed. I've read a lot of the upgrade advisor help file and can't see anything in there that our application would have trouble with.

Therefore, If i've run the upgrade advisor and I have no issues (and I can't see anything in the help file that would cause us problems) then presumably the next step is to restore our databases in SQL Server 2005 and change the compatibility level to 90 and start testing our applications directly?

|||There are noguarantees! :)
In your place I would check whether I am aware of any points detailed in the above link that would impede your applications functionality or performance.
I'd then restore the database in SQL 2005 and start testing, if I hit issues that might be compability related, then I'd drop the compatability level to try to resolve them.sql

Making better queries

Hello,
I am in process of reworking a web application, that is quite data-base
intensive. Right now I am focused on the view that executes the highest
number of queries. Telling you the full picture would be very verbose - the
database structure is quite compex, etc. What I am looking for, is some kind
of buide, how to write a better queries. Why one approach is better than the
other.
For example, the decisions I face, are:
- What is the most effective way to get only subset of records from ordered
query where are tens of thousands elements? I need this to enable paging
through the recordset.
- Why executing many queries like "SELECT myField FROM myTable WHERE
id=nn", just changing nn, sometimes is faster than creating a query with
subquery like "SELECT (SELECT myField FROM myTable WHERE id=outTable.id)
FROM outTable where id in (...)"
- Or, perhaps, alternative to subquery is a join, like in "SELECT * FROM
outTable LEFT JOIN myTable ON outTable.id=myTable.id WHERE outTable.id in
(...)"
Well, I am sure there is no short answer to questions like this, therefore I
need some wisdom, maybe there is some online article about this? I came to
conclusion that I need serious theory to complete my work, because my local
SQL server here executes my "improved" queries faster than the old, but the
SQL server of the webhoster executes them slower than the old ones. It
escapes me, why there should be such a difference, given that the data and
indexes are exactly the same on the two databases.
I will be gratefuly for any hint.
Pavils>What is the most effective way to get only subset of records from ordered
>query where are tens of thousands elements? I need this to enable paging
>through the recordset.
> - Why executing many queries like "SELECT myField FROM myTable WHERE
>id=nn", just changing nn, sometimes is faster than creating a query with
>subquery like "SELECT (SELECT myField FROM myTable WHERE id=outTable.id)
>FROM outTable where id in (...)"
>- Or, perhaps, alternative to subquery is a join, like in "SELECT * FROM
>outTable LEFT JOIN myTable ON outTable.id=myTable.id WHERE outTable.id in
>(...)"
I'd say it depends on what your trying to accomplish. The frist query
is the fastest and the last query is good if the join is needed.
Otherwise don't use joins if you don't need too, unless necessary, try
to use inner joins.
Other considerations too look at when comparing performance of the two
servers is memory, hard drive types and speeds, location, cpu speed and
server load.|||Have you looked at the execution plan for each of the queries. that will
tell you what SQL Server is doing behind the scenes, which will tell you
which query is the most efficient to run.
"Izzy" wrote:

>
> I'd say it depends on what your trying to accomplish. The frist query
> is the fastest and the last query is good if the join is needed.
> Otherwise don't use joins if you don't need too, unless necessary, try
> to use inner joins.
> Other considerations too look at when comparing performance of the two
> servers is memory, hard drive types and speeds, location, cpu speed and
> server load.
>

Making better queries

Hello,
I am in process of reworking a web application, that is quite data-base
intensive. Right now I am focused on the view that executes the highest
number of queries. Telling you the full picture would be very verbose - the
database structure is quite compex, etc. What I am looking for, is some kind
of buide, how to write a better queries. Why one approach is better than the
other.
For example, the decisions I face, are:
- What is the most effective way to get only subset of records from ordered
query where are tens of thousands elements? I need this to enable paging
through the recordset.
- Why executing many queries like "SELECT myField FROM myTable WHERE
id=nn", just changing nn, sometimes is faster than creating a query with
subquery like "SELECT (SELECT myField FROM myTable WHERE id=outTable.id)
FROM outTable where id in (...)"
- Or, perhaps, alternative to subquery is a join, like in "SELECT * FROM
outTable LEFT JOIN myTable ON outTable.id=myTable.id WHERE outTable.id in
(...)"
Well, I am sure there is no short answer to questions like this, therefore I
need some wisdom, maybe there is some online article about this? I came to
conclusion that I need serious theory to complete my work, because my local
SQL server here executes my "improved" queries faster than the old, but the
SQL server of the webhoster executes them slower than the old ones. It
escapes me, why there should be such a difference, given that the data and
indexes are exactly the same on the two databases.
I will be gratefuly for any hint.
Pavils>What is the most effective way to get only subset of records from ordered
>query where are tens of thousands elements? I need this to enable paging
>through the recordset.
> - Why executing many queries like "SELECT myField FROM myTable WHERE
>id=nn", just changing nn, sometimes is faster than creating a query with
>subquery like "SELECT (SELECT myField FROM myTable WHERE id=outTable.id)
>FROM outTable where id in (...)"
>- Or, perhaps, alternative to subquery is a join, like in "SELECT * FROM
>outTable LEFT JOIN myTable ON outTable.id=myTable.id WHERE outTable.id in
>(...)"
I'd say it depends on what your trying to accomplish. The frist query
is the fastest and the last query is good if the join is needed.
Otherwise don't use joins if you don't need too, unless necessary, try
to use inner joins.
Other considerations too look at when comparing performance of the two
servers is memory, hard drive types and speeds, location, cpu speed and
server load.|||Have you looked at the execution plan for each of the queries. that will
tell you what SQL Server is doing behind the scenes, which will tell you
which query is the most efficient to run.
"Izzy" wrote:
> >What is the most effective way to get only subset of records from ordered
> >query where are tens of thousands elements? I need this to enable paging
> >through the recordset.
> > - Why executing many queries like "SELECT myField FROM myTable WHERE
> >id=nn", just changing nn, sometimes is faster than creating a query with
> >subquery like "SELECT (SELECT myField FROM myTable WHERE id=outTable.id)
> >FROM outTable where id in (...)"
> >- Or, perhaps, alternative to subquery is a join, like in "SELECT * FROM
> >outTable LEFT JOIN myTable ON outTable.id=myTable.id WHERE outTable.id in
> >(...)"
>
> I'd say it depends on what your trying to accomplish. The frist query
> is the fastest and the last query is good if the join is needed.
> Otherwise don't use joins if you don't need too, unless necessary, try
> to use inner joins.
> Other considerations too look at when comparing performance of the two
> servers is memory, hard drive types and speeds, location, cpu speed and
> server load.
>

Friday, March 23, 2012

Making an Access - SQL db solution portable

I have an Access application which runs in a server enviroment where I have
an SQL server that the Access connects to. The customer is so happy with my
soultion and told another company about it, they would like something like
that, so I need to make a copy of the setup to a cd to send to the other
company - as a demo. They have no employees with enough IT knowledge to
install a SQL Server/MSDE and the import the database and setting up Access
to connect to the new server. Remote control is not an option, neither is
"local control" since they will not pay for my trip (transatlantic) unless
they want me to make a soultion for them...
I need to take the solution and make it portable. But I am not sure how to
do it, I need a "downsizing" wizard or something? A solution could be to
make "some kind of installer" which installes a MSDE and loads the data into
it and connects the Access database to the new db server. Probably the best
solution, if there is no easy way to make it portable.
I would asume there are some tools available for this or similar purposes,
but I don't know any...
My concern is also the fact that there are some views in the SQL database
and also a lot of the VBA code in forms and reports has been modified to fit
the SQL, during upsizing some years back... I wouldn't like to re-write the
rewritten code, just for a demo.
I'm pretty sure I'm not the only one who has ever wanted to do this, if you
have done it, please let me know how. I welcome any suggestions. :o)
Thanks in advance
Martin Gregersen
martin@.gregersen.dkHow about a simple mssql backup of the database?
Then they could just import the backup database on their system
Pieter
"Martin Gregersen" <martin@.gregersen.dk> wrote in message
news:eWiKjFUlGHA.2420@.TK2MSFTNGP04.phx.gbl...
>I have an Access application which runs in a server enviroment where I have
>an SQL server that the Access connects to. The customer is so happy with my
>soultion and told another company about it, they would like something like
>that, so I need to make a copy of the setup to a cd to send to the other
>company - as a demo. They have no employees with enough IT knowledge to
>install a SQL Server/MSDE and the import the database and setting up Access
>to connect to the new server. Remote control is not an option, neither is
>"local control" since they will not pay for my trip (transatlantic) unless
>they want me to make a soultion for them...
> I need to take the solution and make it portable. But I am not sure how to
> do it, I need a "downsizing" wizard or something? A solution could be to
> make "some kind of installer" which installes a MSDE and loads the data
> into it and connects the Access database to the new db server. Probably
> the best solution, if there is no easy way to make it portable.
> I would asume there are some tools available for this or similar purposes,
> but I don't know any...
> My concern is also the fact that there are some views in the SQL database
> and also a lot of the VBA code in forms and reports has been modified to
> fit the SQL, during upsizing some years back... I wouldn't like to
> re-write the rewritten code, just for a demo.
> I'm pretty sure I'm not the only one who has ever wanted to do this, if
> you have done it, please let me know how. I welcome any suggestions. :o)
> Thanks in advance
> Martin Gregersen
> martin@.gregersen.dk
>
>|||How about a simple mssql backup of the database?
Then they could just import the backup database on their system
Pieter
"Martin Gregersen" <martin@.gregersen.dk> wrote in message
news:eWiKjFUlGHA.2420@.TK2MSFTNGP04.phx.gbl...
>I have an Access application which runs in a server enviroment where I have
>an SQL server that the Access connects to. The customer is so happy with my
>soultion and told another company about it, they would like something like
>that, so I need to make a copy of the setup to a cd to send to the other
>company - as a demo. They have no employees with enough IT knowledge to
>install a SQL Server/MSDE and the import the database and setting up Access
>to connect to the new server. Remote control is not an option, neither is
>"local control" since they will not pay for my trip (transatlantic) unless
>they want me to make a soultion for them...
> I need to take the solution and make it portable. But I am not sure how to
> do it, I need a "downsizing" wizard or something? A solution could be to
> make "some kind of installer" which installes a MSDE and loads the data
> into it and connects the Access database to the new db server. Probably
> the best solution, if there is no easy way to make it portable.
> I would asume there are some tools available for this or similar purposes,
> but I don't know any...
> My concern is also the fact that there are some views in the SQL database
> and also a lot of the VBA code in forms and reports has been modified to
> fit the SQL, during upsizing some years back... I wouldn't like to
> re-write the rewritten code, just for a demo.
> I'm pretty sure I'm not the only one who has ever wanted to do this, if
> you have done it, please let me know how. I welcome any suggestions. :o)
> Thanks in advance
> Martin Gregersen
> martin@.gregersen.dk
>
>
---
I am using the free version of SPAMfighter for private users.
It has removed 4026 spam emails to date.
Paying users do not have this message in their emails.
Get the free SPAMfighter here: http://www.spamfighter.com/len|||I would say tell them to install MSDE and be done with it. If that's not an
option maybe you could set up a remote demo over the internet? Run it
locally on your computer and let them view it in the web browser using
NetMeeting or whatever.
"Martin Gregersen" <martin@.gregersen.dk> wrote in message
news:eWiKjFUlGHA.2420@.TK2MSFTNGP04.phx.gbl...
>I have an Access application which runs in a server enviroment where I have
>an SQL server that the Access connects to. The customer is so happy with my
>soultion and told another company about it, they would like something like
>that, so I need to make a copy of the setup to a cd to send to the other
>company - as a demo. They have no employees with enough IT knowledge to
>install a SQL Server/MSDE and the import the database and setting up Access
>to connect to the new server. Remote control is not an option, neither is
>"local control" since they will not pay for my trip (transatlantic) unless
>they want me to make a soultion for them...
> I need to take the solution and make it portable. But I am not sure how to
> do it, I need a "downsizing" wizard or something? A solution could be to
> make "some kind of installer" which installes a MSDE and loads the data
> into it and connects the Access database to the new db server. Probably
> the best solution, if there is no easy way to make it portable.
> I would asume there are some tools available for this or similar purposes,
> but I don't know any...
> My concern is also the fact that there are some views in the SQL database
> and also a lot of the VBA code in forms and reports has been modified to
> fit the SQL, during upsizing some years back... I wouldn't like to
> re-write the rewritten code, just for a demo.
> I'm pretty sure I'm not the only one who has ever wanted to do this, if
> you have done it, please let me know how. I welcome any suggestions. :o)
> Thanks in advance
> Martin Gregersen
> martin@.gregersen.dk
>
>|||Hi Martin,
Actually - you can make a setup, which will install MSDE, attach database
and then install all necessary components to run your application - but this
also time consuming task if you never did so.
I think that installing your application on windowsxp and then let them
connect to it with remote desktop it order to try - is most realistic option
for you
Best regards,
___________
Alex Dybenko (MVP)
http://alexdyb.blogspot.com
http://www.PointLtd.com
"Martin Gregersen" <martin@.gregersen.dk> wrote in message
news:eWiKjFUlGHA.2420@.TK2MSFTNGP04.phx.gbl...
>I have an Access application which runs in a server enviroment where I have
>an SQL server that the Access connects to. The customer is so happy with my
>soultion and told another company about it, they would like something like
>that, so I need to make a copy of the setup to a cd to send to the other
>company - as a demo. They have no employees with enough IT knowledge to
>install a SQL Server/MSDE and the import the database and setting up Access
>to connect to the new server. Remote control is not an option, neither is
>"local control" since they will not pay for my trip (transatlantic) unless
>they want me to make a soultion for them...
> I need to take the solution and make it portable. But I am not sure how to
> do it, I need a "downsizing" wizard or something? A solution could be to
> make "some kind of installer" which installes a MSDE and loads the data
> into it and connects the Access database to the new db server. Probably
> the best solution, if there is no easy way to make it portable.
> I would asume there are some tools available for this or similar purposes,
> but I don't know any...
> My concern is also the fact that there are some views in the SQL database
> and also a lot of the VBA code in forms and reports has been modified to
> fit the SQL, during upsizing some years back... I wouldn't like to
> re-write the rewritten code, just for a demo.
> I'm pretty sure I'm not the only one who has ever wanted to do this, if
> you have done it, please let me know how. I welcome any suggestions. :o)
> Thanks in advance
> Martin Gregersen
> martin@.gregersen.dk
>
>|||Hi Alex
I would like if you could tell me how to make such an installer, then I will
know and can make the best decission. They really need a copy to play with,
not just a demonstration online, they need to take every process of their
production into consideration and then see would features they like/dislike
and so on.
Also I would like to know just to know ;o)
Thanks
Martin
"Alex Dybenko" <alexdyb@.PLEASE.cemi.NO.rssi.SPAM.ru> wrote in message
news:OzFt1nUlGHA.1208@.TK2MSFTNGP02.phx.gbl...
> Hi Martin,
> Actually - you can make a setup, which will install MSDE, attach database
> and then install all necessary components to run your application - but
> this also time consuming task if you never did so.
> I think that installing your application on windowsxp and then let them
> connect to it with remote desktop it order to try - is most realistic
> option for you
>
> --
> Best regards,
> ___________
> Alex Dybenko (MVP)
> http://alexdyb.blogspot.com
> http://www.PointLtd.com
>
> "Martin Gregersen" <martin@.gregersen.dk> wrote in message
> news:eWiKjFUlGHA.2420@.TK2MSFTNGP04.phx.gbl...
>|||Hi Martin,
personally - I use Wise installation system, but you can also try some free
installer, for example see
http://alexdyb.blogspot.com/2006/04...-installer.html
then you can download MSDE setup package from Microsoft site, and include in
your package
now you need to build a script to run MSDE setup, copy database files,
application files, attach database (I use attachDB to do so:
http://www.pointltd.com/Products/Details.asp?dlID=46)
Best regards,
___________
Alex Dybenko (MVP)
http://alexdyb.blogspot.com
http://www.PointLtd.com
"Martin Gregersen" <martin@.gregersen.dk> wrote in message
news:uEFXGfclGHA.4708@.TK2MSFTNGP04.phx.gbl...
> Hi Alex
> I would like if you could tell me how to make such an installer, then I
> will know and can make the best decission. They really need a copy to play
> with, not just a demonstration online, they need to take every process of
> their production into consideration and then see would features they
> like/dislike and so on.
> Also I would like to know just to know ;o)
> Thanks
> Martin
>
> "Alex Dybenko" <alexdyb@.PLEASE.cemi.NO.rssi.SPAM.ru> wrote in message
> news:OzFt1nUlGHA.1208@.TK2MSFTNGP02.phx.gbl...
>

Making adp stand alone

Hi, I have an adp with SQL sever backend. I now need to somehow make the application stand-alone on a laptop. The laptop will not have SQl server installed. The only way I can think of is to make my adp becomes mdb. Can you please tell me if there is any other ways to make the application become stand-alone? Please advise.

Thanks so much!

SHKwrite it with vb|||Can you tell me more?

Making a create statement from existing database

We have a Peoplesoft application built over MS server 2000. The peoplesoft
application has created a table in ms server via its application designer
where the field types, sizes, indexes are automatically generated from the
data dictionary and search keys etc.
What I would like to know is how can I inquire via query analyser the
structure of these tables ( sort of reverse enginering the SQL DDL statement
s
) so that I can then end up with an SQL create statement etc.
thanks.listTableColumns should get you pretty close:
http://www.aspfaq.com/2177
"JD" <JD@.discussions.microsoft.com> wrote in message
news:56C8824E-D60E-4965-A62F-55B893D8F7F4@.microsoft.com...
> We have a Peoplesoft application built over MS server 2000. The peoplesoft
> application has created a table in ms server via its application designer
> where the field types, sizes, indexes are automatically generated from the
> data dictionary and search keys etc.
> What I would like to know is how can I inquire via query analyser the
> structure of these tables ( sort of reverse enginering the SQL DDL
> statements
> ) so that I can then end up with an SQL create statement etc.
> thanks.|||"JD" <JD@.discussions.microsoft.com> wrote in message
news:56C8824E-D60E-4965-A62F-55B893D8F7F4@.microsoft.com...
> We have a Peoplesoft application built over MS server 2000. The peoplesoft
> application has created a table in ms server via its application designer
> where the field types, sizes, indexes are automatically generated from the
> data dictionary and search keys etc.
> What I would like to know is how can I inquire via query analyser the
> structure of these tables ( sort of reverse enginering the SQL DDL
> statements
> ) so that I can then end up with an SQL create statement etc.
> thanks.
Take a look at INFORMATION_SCHEMA in the Books Online. In particular, you
will want to pay attention to INFORMATION_SCHEMA.TABLES and .COLUMNS.
As for the indexes and so forth, that will be a bit more tricky.
Rick Sawtell
MCT, MCSD, MCDBA|||If you can use Enterprise Manager, there is a wizard that generates scripts.
You can pick the specific table you're interested in and save it creation
script. There's options to include indexes, primary keys, etc.
Joe
"Aaron Bertrand [SQL Server MVP]" wrote:

> listTableColumns should get you pretty close:
> http://www.aspfaq.com/2177
>
> "JD" <JD@.discussions.microsoft.com> wrote in message
> news:56C8824E-D60E-4965-A62F-55B893D8F7F4@.microsoft.com...
>
>|||Try Creating a SQL Script from Enterprise Manager. Save it and then open it
up with Query Analyzer
"JD" <JD@.discussions.microsoft.com> escribi en el mensaje
news:56C8824E-D60E-4965-A62F-55B893D8F7F4@.microsoft.com...
> We have a Peoplesoft application built over MS server 2000. The peoplesoft
> application has created a table in ms server via its application designer
> where the field types, sizes, indexes are automatically generated from the
> data dictionary and search keys etc.
> What I would like to know is how can I inquire via query analyser the
> structure of these tables ( sort of reverse enginering the SQL DDL
> statements
> ) so that I can then end up with an SQL create statement etc.
> thanks.

Making a copy of an SQL 7 database into an MSDE environment

We have developed an application for Small Business
Server (SQL) on a system that is running MSDE. All
programming and testing was conducted on a remote,
standalone system, and when completed, we were able to
move appropriate copies to the LAN via an external 80GB
Western Digital USB attached portable drive.
Is it possible to copy one or more or the SQL databases
(all tables) from the SBS SQL server to an MSDE system?
(ie a network attached laptop).
I would appreciate your assistance and comments.
Regards...Dave K.
hi Dave,
"dkalling" <dkalling@.cnx2.com> ha scritto nel messaggio
news:04c001c4eddc$579de490$a401280a@.phx.gbl
> We have developed an application for Small Business
> Server (SQL) on a system that is running MSDE. All
> programming and testing was conducted on a remote,
> standalone system, and when completed, we were able to
> move appropriate copies to the LAN via an external 80GB
> Western Digital USB attached portable drive.
> Is it possible to copy one or more or the SQL databases
> (all tables) from the SBS SQL server to an MSDE system?
> (ie a network attached laptop).
> I would appreciate your assistance and comments.
> Regards...Dave K.
as you can't use DTS to manage MSDE instances (and more you say that your
SQL Server is a version 7.0 server), you have to rely on backup/restore
and/or sp_detach_db/sp_attach_db solutions
please keep in mind you will probably experiencing orphaned users problems
after that operation(s), you can resolve using system stored procedure
sp_change_users_login
(http://www.sqlservercentral.com/colu...okenlogins.asp)
you can move users databases this way only from 7.0 version to 2000 version,
and not vice versa
Andrea Montanari (Microsoft MVP - SQL Server)
http://www.asql.biz/DbaMgr.shtmhttp://italy.mvps.org
DbaMgr2k ver 0.9.1 - DbaMgr ver 0.55.1
(my vb6+sql-dmo little try to provide MS MSDE 1.0 and MSDE 2000 a visual
interface)
-- remove DMO to reply
sql

Making a connection to a sql server via webmatrix

Hi all,
i'm making a webpage via the walkthrough of webmatrix. I use the tutorial 'Build an End-to-End Application (with C#.NET) '. The problem is that this tutorial works with an access db. I'll try to start the same thing but using an sql server.

Nowhere i can't find (because i don't look at the right place i gess) how i have to make a sqlconnection via webmatrix with c# using a keyfield to filter my data and to fill out a datagrid.

can somebody help me please ?

thnxWell, there are examples using MSDE at the same site (ASP.NET Web Matrix Project Guided Tour), so maybe you could piece it together.

The approach should be very similar -- generally you use the "Sql" prefix everywhere instead of "Oledb", and the connection string would need to be updated.

Terri|||Thnx Terri for your reply. Like you can gess i never done anything with asp or c#. I always worked with vfp and sqlserver.

Kurt|||Once you've got more of the code together, let us know if you are still having problems. We should be able to help fill in the gaps. (Although theData Access forum will probably be a better place to post since it's an ADO.Net topic.)

Terri

Wednesday, March 21, 2012

Make the Login box go away!

I'm trying to incorporate the /ReportServer virtual into our application web
site so we can point the Report Viewer control to /ReportServer rather than
<default web site's IP>/ReportServer. I'm trying to remove authentication
from <app>/ReportServer, but I've been unable to keep it from popping up
that blasted login dialog box. I've briefly tried using the FormsAuth
sample and even rewrote it to always return True from all the authentication
functions, but neither solved my problem.
The application is under Forms Auth. I just want the ReportServer virtual
to run in that context. At this point, I don't even care if it's really
keeping authentication or just letting anyone who happens to type in
http://<our_app>/ReportServer go uncontested. It's extremely frustrating,
and it doesn't work for any users as it is now.
This is SQL Server Standard, so I don't know if custom security extensions
(assuming I really had any clue as to how they worked or how to set them up)
would even work (I came across a page that says only Enterprise supports
them).To my knowledge, for IE to give your windows authentication credentials
automatically to IIS, you have to adresse the website using a machine name.
Use something like http://computername/ReportServer
Suppose your server is named BigBox.leetdomain.com
Address it using http://BigBox/ReportServer
I never had to mess around with the report server security as we want
windows authentication and the report server will not be used externally. It
seems to be configured fine by default.
"DJM" wrote:
> I'm trying to incorporate the /ReportServer virtual into our application web
> site so we can point the Report Viewer control to /ReportServer rather than
> <default web site's IP>/ReportServer. I'm trying to remove authentication
> from <app>/ReportServer, but I've been unable to keep it from popping up
> that blasted login dialog box. I've briefly tried using the FormsAuth
> sample and even rewrote it to always return True from all the authentication
> functions, but neither solved my problem.
> The application is under Forms Auth. I just want the ReportServer virtual
> to run in that context. At this point, I don't even care if it's really
> keeping authentication or just letting anyone who happens to type in
> http://<our_app>/ReportServer go uncontested. It's extremely frustrating,
> and it doesn't work for any users as it is now.
> This is SQL Server Standard, so I don't know if custom security extensions
> (assuming I really had any clue as to how they worked or how to set them up)
> would even work (I came across a page that says only Enterprise supports
> them).
>
>|||The Forms Authentication sample from MSDN gives you instructions on how to
restore to default non-forms-authentication settings.
Basically, it's not recommended since you'll have to re-do your report
permissions. And if you don't have the original .config files backed up,
you'll have a VERY difficult time.
--
'(' Jeff A. Stucker
\
Business Intelligence
www.criadvantage.com
---
"DJM" <msnews@.puddlestheshark.com> wrote in message
news:e6Cz03NzEHA.2600@.TK2MSFTNGP09.phx.gbl...
> I'm trying to incorporate the /ReportServer virtual into our application
> web
> site so we can point the Report Viewer control to /ReportServer rather
> than
> <default web site's IP>/ReportServer. I'm trying to remove authentication
> from <app>/ReportServer, but I've been unable to keep it from popping up
> that blasted login dialog box. I've briefly tried using the FormsAuth
> sample and even rewrote it to always return True from all the
> authentication
> functions, but neither solved my problem.
> The application is under Forms Auth. I just want the ReportServer virtual
> to run in that context. At this point, I don't even care if it's really
> keeping authentication or just letting anyone who happens to type in
> http://<our_app>/ReportServer go uncontested. It's extremely frustrating,
> and it doesn't work for any users as it is now.
> This is SQL Server Standard, so I don't know if custom security extensions
> (assuming I really had any clue as to how they worked or how to set them
> up)
> would even work (I came across a page that says only Enterprise supports
> them).
>
>|||But the standard is Windows Authentication. I still get the
username/password dialog when trying to access a report via report viewer
control from my website.
"Jeff A. Stucker" <jeff@.mobilize.net> wrote in message
news:O$FUn9OzEHA.3708@.TK2MSFTNGP14.phx.gbl...
> The Forms Authentication sample from MSDN gives you instructions on how to
> restore to default non-forms-authentication settings.
> Basically, it's not recommended since you'll have to re-do your report
> permissions. And if you don't have the original .config files backed up,
> you'll have a VERY difficult time.
> --
> '(' Jeff A. Stucker
> \
> Business Intelligence
> www.criadvantage.com
> ---
> "DJM" <msnews@.puddlestheshark.com> wrote in message
> news:e6Cz03NzEHA.2600@.TK2MSFTNGP09.phx.gbl...
>> I'm trying to incorporate the /ReportServer virtual into our application
>> web
>> site so we can point the Report Viewer control to /ReportServer rather
>> than
>> <default web site's IP>/ReportServer. I'm trying to remove
>> authentication
>> from <app>/ReportServer, but I've been unable to keep it from popping up
>> that blasted login dialog box. I've briefly tried using the FormsAuth
>> sample and even rewrote it to always return True from all the
>> authentication
>> functions, but neither solved my problem.
>> The application is under Forms Auth. I just want the ReportServer
>> virtual
>> to run in that context. At this point, I don't even care if it's really
>> keeping authentication or just letting anyone who happens to type in
>> http://<our_app>/ReportServer go uncontested. It's extremely
>> frustrating,
>> and it doesn't work for any users as it is now.
>> This is SQL Server Standard, so I don't know if custom security
>> extensions
>> (assuming I really had any clue as to how they worked or how to set them
>> up)
>> would even work (I came across a page that says only Enterprise supports
>> them).
>>
>|||And since the report server *is* being accessed externally, it's quite
definitely not fine for our needs.
"/dev/null" <devnull@.discussions.microsoft.com> wrote in message
news:2BD4677A-BEF2-4048-92B9-316F38813E85@.microsoft.com...
> To my knowledge, for IE to give your windows authentication credentials
> automatically to IIS, you have to adresse the website using a machine
> name.
> Use something like http://computername/ReportServer
> Suppose your server is named BigBox.leetdomain.com
> Address it using http://BigBox/ReportServer
> I never had to mess around with the report server security as we want
> windows authentication and the report server will not be used externally.
> It
> seems to be configured fine by default.
>
> "DJM" wrote:
>> I'm trying to incorporate the /ReportServer virtual into our application
>> web
>> site so we can point the Report Viewer control to /ReportServer rather
>> than
>> <default web site's IP>/ReportServer. I'm trying to remove
>> authentication
>> from <app>/ReportServer, but I've been unable to keep it from popping up
>> that blasted login dialog box. I've briefly tried using the FormsAuth
>> sample and even rewrote it to always return True from all the
>> authentication
>> functions, but neither solved my problem.
>> The application is under Forms Auth. I just want the ReportServer
>> virtual
>> to run in that context. At this point, I don't even care if it's really
>> keeping authentication or just letting anyone who happens to type in
>> http://<our_app>/ReportServer go uncontested. It's extremely
>> frustrating,
>> and it doesn't work for any users as it is now.
>> This is SQL Server Standard, so I don't know if custom security
>> extensions
>> (assuming I really had any clue as to how they worked or how to set them
>> up)
>> would even work (I came across a page that says only Enterprise supports
>> them).
>>
>>|||Ok, I've set Authentication mode="None", I've set the /ReportServer virtual
to allow Anonymous access as IUSR, I've granted IUSR_GROUP (local group
containing the IUSR, IWAM, and ASP.NET users) access to the \MSSQL\Reporting
Services\ReportServer folder (and files and subfolders), and I've granted
the IUSR_GROUP the Browser role to all reports.
So why, when using the Report Viewer web control, do I see a login box?!?|||Does anyone have any advice or suggestions here? I still haven't resolved
this.
"DJM" <msnews@.puddlestheshark.com> wrote in message
news:uLeyyLnzEHA.352@.TK2MSFTNGP14.phx.gbl...
> Ok, I've set Authentication mode="None", I've set the /ReportServer
> virtual to allow Anonymous access as IUSR, I've granted IUSR_GROUP (local
> group containing the IUSR, IWAM, and ASP.NET users) access to the
> \MSSQL\Reporting Services\ReportServer folder (and files and subfolders),
> and I've granted the IUSR_GROUP the Browser role to all reports.
> So why, when using the Report Viewer web control, do I see a login box?!?
>|||You have two options:
1. Generating the report on the server side of the application by using the
Render SOAP API. The advantage of this approach is that it is more secure
since the user doesn't see the report URL (everything takes place on the
server). The tradeoff is that the interactive features (drilldown,
drillthrough, etc.) will not work with SOAP since their require direct
access to the Report Server by URL. If you decide to take this approach, you
can pass the web app identity to the Report Server and grant a minimum set
of permissions in RS to this account.
2. Replace the RS Windows security with Forms Authentication by writing a
custom security extension. This will allow you to incorporate interactive
features in your reports. In this scenario, the reports will be requested on
the client side of the application (e.g. by using the Report Viewer sample
control). If you decide to take this approach check out the sample security
extension from MS at
(http://msdn.microsoft.com/library/?url=/library/en-us/dnsql2k/html/ufairs.a
sp?frame=true#ufairs_topic3).
So, you have to carefully weight out your requirements for security,
reporting features and your application architecture to determine the best
integration scenario.
--
Hope this helps.
Rags Iyer
"DJM" wrote:
> I'm trying to incorporate the /ReportServer virtual into our application web
> site so we can point the Report Viewer control to /ReportServer rather than
> <default web site's IP>/ReportServer. I'm trying to remove authentication
> from <app>/ReportServer, but I've been unable to keep it from popping up
> that blasted login dialog box. I've briefly tried using the FormsAuth
> sample and even rewrote it to always return True from all the authentication
> functions, but neither solved my problem.
> The application is under Forms Auth. I just want the ReportServer virtual
> to run in that context. At this point, I don't even care if it's really
> keeping authentication or just letting anyone who happens to type in
> http://<our_app>/ReportServer go uncontested. It's extremely frustrating,
> and it doesn't work for any users as it is now.
> This is SQL Server Standard, so I don't know if custom security extensions
> (assuming I really had any clue as to how they worked or how to set them up)
> would even work (I came across a page that says only Enterprise supports
> them).
>
>|||The second option would be ideal, but if you'll notice, I tried that and was
unable to get it to make a shred of difference. Maybe I'm just not smart
enough to figure it out, but it's not working for me.
"Rags Iyer" <RagsIyer@.discussions.microsoft.com> wrote in message
news:A2AD6EB1-4CE8-4305-8063-8EE6AC9E1828@.microsoft.com...
> You have two options:
> 1. Generating the report on the server side of the application by using
> the
> Render SOAP API. The advantage of this approach is that it is more secure
> since the user doesn't see the report URL (everything takes place on the
> server). The tradeoff is that the interactive features (drilldown,
> drillthrough, etc.) will not work with SOAP since their require direct
> access to the Report Server by URL. If you decide to take this approach,
> you
> can pass the web app identity to the Report Server and grant a minimum set
> of permissions in RS to this account.
> 2. Replace the RS Windows security with Forms Authentication by writing a
> custom security extension. This will allow you to incorporate interactive
> features in your reports. In this scenario, the reports will be requested
> on
> the client side of the application (e.g. by using the Report Viewer sample
> control). If you decide to take this approach check out the sample
> security
> extension from MS at
> (http://msdn.microsoft.com/library/?url=/library/en-us/dnsql2k/html/ufairs.a
> sp?frame=true#ufairs_topic3).
> So, you have to carefully weight out your requirements for security,
> reporting features and your application architecture to determine the best
> integration scenario.
> --
> Hope this helps.
> Rags Iyer
> "DJM" wrote:
>> I'm trying to incorporate the /ReportServer virtual into our application
>> web
>> site so we can point the Report Viewer control to /ReportServer rather
>> than
>> <default web site's IP>/ReportServer. I'm trying to remove
>> authentication
>> from <app>/ReportServer, but I've been unable to keep it from popping up
>> that blasted login dialog box. I've briefly tried using the FormsAuth
>> sample and even rewrote it to always return True from all the
>> authentication
>> functions, but neither solved my problem.
>> The application is under Forms Auth. I just want the ReportServer
>> virtual
>> to run in that context. At this point, I don't even care if it's really
>> keeping authentication or just letting anyone who happens to type in
>> http://<our_app>/ReportServer go uncontested. It's extremely
>> frustrating,
>> and it doesn't work for any users as it is now.
>> This is SQL Server Standard, so I don't know if custom security
>> extensions
>> (assuming I really had any clue as to how they worked or how to set them
>> up)
>> would even work (I came across a page that says only Enterprise supports
>> them).
>>
>>|||Is the Login Box still popping up when Forms Authetication is Implemented.?
"DJM" wrote:
> The second option would be ideal, but if you'll notice, I tried that and was
> unable to get it to make a shred of difference. Maybe I'm just not smart
> enough to figure it out, but it's not working for me.
> "Rags Iyer" <RagsIyer@.discussions.microsoft.com> wrote in message
> news:A2AD6EB1-4CE8-4305-8063-8EE6AC9E1828@.microsoft.com...
> > You have two options:
> >
> > 1. Generating the report on the server side of the application by using
> > the
> > Render SOAP API. The advantage of this approach is that it is more secure
> > since the user doesn't see the report URL (everything takes place on the
> > server). The tradeoff is that the interactive features (drilldown,
> > drillthrough, etc.) will not work with SOAP since their require direct
> > access to the Report Server by URL. If you decide to take this approach,
> > you
> > can pass the web app identity to the Report Server and grant a minimum set
> > of permissions in RS to this account.
> >
> > 2. Replace the RS Windows security with Forms Authentication by writing a
> > custom security extension. This will allow you to incorporate interactive
> > features in your reports. In this scenario, the reports will be requested
> > on
> > the client side of the application (e.g. by using the Report Viewer sample
> > control). If you decide to take this approach check out the sample
> > security
> > extension from MS at
> > (http://msdn.microsoft.com/library/?url=/library/en-us/dnsql2k/html/ufairs.a
> > sp?frame=true#ufairs_topic3).
> >
> > So, you have to carefully weight out your requirements for security,
> > reporting features and your application architecture to determine the best
> > integration scenario.
> > --
> > Hope this helps.
> >
> > Rags Iyer
> >
> > "DJM" wrote:
> >
> >> I'm trying to incorporate the /ReportServer virtual into our application
> >> web
> >> site so we can point the Report Viewer control to /ReportServer rather
> >> than
> >> <default web site's IP>/ReportServer. I'm trying to remove
> >> authentication
> >> from <app>/ReportServer, but I've been unable to keep it from popping up
> >> that blasted login dialog box. I've briefly tried using the FormsAuth
> >> sample and even rewrote it to always return True from all the
> >> authentication
> >> functions, but neither solved my problem.
> >>
> >> The application is under Forms Auth. I just want the ReportServer
> >> virtual
> >> to run in that context. At this point, I don't even care if it's really
> >> keeping authentication or just letting anyone who happens to type in
> >> http://<our_app>/ReportServer go uncontested. It's extremely
> >> frustrating,
> >> and it doesn't work for any users as it is now.
> >>
> >> This is SQL Server Standard, so I don't know if custom security
> >> extensions
> >> (assuming I really had any clue as to how they worked or how to set them
> >> up)
> >> would even work (I came across a page that says only Enterprise supports
> >> them).
> >>
> >>
> >>
> >>
>
>|||Yes.
"Rags Iyer" <RagsIyer@.discussions.microsoft.com> wrote in message
news:C574F74E-C580-47A4-86AD-BCD62253C700@.microsoft.com...
> Is the Login Box still popping up when Forms Authetication is
> Implemented.?|||Please check wherther the Security implemenation for Forms Authetication was
properly implemented.The authetication in the Rs Config File needs to be
changed to Forms Authentication and all the required policy is set.
Regards,
Rags Iyer
"DJM" wrote:
> Yes.
> "Rags Iyer" <RagsIyer@.discussions.microsoft.com> wrote in message
> news:C574F74E-C580-47A4-86AD-BCD62253C700@.microsoft.com...
> >
> > Is the Login Box still popping up when Forms Authetication is
> > Implemented.?
>
>|||Please check wherther the Security implemenation for Forms Authetication was
properly implemented.The authetication in the Rs Config File needs to be
changed to Forms Authentication and all the required policy is set.
Regards,
Rags Iyer
"DJM" wrote:
> Yes.
> "Rags Iyer" <RagsIyer@.discussions.microsoft.com> wrote in message
> news:C574F74E-C580-47A4-86AD-BCD62253C700@.microsoft.com...
> >
> > Is the Login Box still popping up when Forms Authetication is
> > Implemented.?
>
>|||I did that according to the documentation (adding Forms to the
authentication types or wherever that is, and changing authentication mode
to Forms in the web.config), and I was still getting the login box.
What gets me is that box is still appearing even when I set the
authentication mode to None.
"Rags Iyer" <RagsIyer@.discussions.microsoft.com> wrote in message
news:E5169863-A011-43A4-BAB3-A0627C0A0272@.microsoft.com...
> Please check wherther the Security implemenation for Forms Authetication
> was
> properly implemented.The authetication in the Rs Config File needs to be
> changed to Forms Authentication and all the required policy is set.
> Regards,
> Rags Iyer
> "DJM" wrote:
>> Yes.
>> "Rags Iyer" <RagsIyer@.discussions.microsoft.com> wrote in message
>> news:C574F74E-C580-47A4-86AD-BCD62253C700@.microsoft.com...
>> >
>> > Is the Login Box still popping up when Forms Authetication is
>> > Implemented.?
>>