Showing posts with label SQL. Show all posts
Showing posts with label SQL. Show all posts

Tuesday, July 26, 2011

Using Client Reporting to generate PDFs on the fly

Objective: To create PDF file(or any type supported by RDLC) from an ASP.Net(any .net) application from a in-memory dataset.

First, lets create an ASP.Net application using the new Project creation wizard.

Add a new project item and chose Report(report1.rdlc)

image

What we need now is a dataset, which we can use in reports. To do this, lets add a new item – dataset.

image

lets name it as MyDataset.XSD. Lets open this dataset and add a table using the toolbox. Lets name it as DataTable1 and lets add two columns here Email and User. Lets compile this once so that we generate the dataset model.

image

Next step is to use this in our reports. Lets open the report designer(double click the RDLC added earlier) and add a DataSet to this. On report data panel, say New->Data Set.

image

Now select the Mydataset as the data source and the default table as dataset. Now we have Email and User as columns. Lets leave the name as DataSet1. Now its ready to be used in the report.

If everything goes right, you can add a tablix and associate the DataSet1 with it. Now you should see the fields available for using in reports.

image

I have mapped user and Email fields in the report.

Now lets focus back to our code. Open the markup and drop a report viewer control. This should look something like this.

 
<rsweb:ReportViewer ID="repViewer" runat="server">
</rsweb:ReportViewer>




Lets prepare the data to fill the report data using the C# code. We can do this in two ways.




  1. Use the same dataset(MyDataSet)


  2. Create a new dataset on the fly.





Lets try the second approach. On the code behind, lets create a data set and add a table to it and add some data.




            DataSet ds = new DataSet();
DataTable dt = new DataTable();

dt.Columns.Add("User");
dt.Columns.Add("Email");


dt.Rows.Add("Guru", "Guru@aa.com");
dt.Rows.Add("Guru", "Guru@aa.com");
dt.Rows.Add("Guru", "Guru@aa.com");
dt.Rows.Add("Guru", "Guru@aa.com");
ds.Tables.Add(dt);


Now, lets bind this to the report.



repViewer.Reset(); // follow the same order, reset and then add the data   repViewer.LocalReport.ReportPath = "Report1.rdlc";

reportDataSource rs = new ReportDataSource();
rs.Name = "DataSet1"; // Important: Use the same name as given in the report.
rs.Value = ds.Tables[0];

repViewer.LocalReport.DataSources.Add(rs);



Finally, rendering part. Lets return the response as a PDF file



string mimeType;
string encoding;
string extension;
Warning[] warnings;
string[] streamids;

byte[] reportBytes = repViewer.LocalReport.Render("PDF", null,
out mimeType, out encoding,
out extension, out streamids,
out warnings);

Response.ClearContent(); Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "inline; filename=Test.pdf");
/ Response.AddHeader("Accept-Header", reportBytes.Length.ToString());
Response.ContentType = "application/pdf";
Response.OutputStream.Write(reportBytes, 0, reportBytes.Length);
Response.Flush();
Response.Close();


Only advantage of creating the dataset using XSD(MyDataSet) is that you can use them in the report directly by selecting the element. This will help you a lot while binding. You can also connect to SQL and build your data set and use it for report design. Later you can build your own dataset like we have done and use it by providing the same name.Following SQL statement will do the job for you.



Select 'Guru' as User, select 'Test' as Email





Screen shot below is the output, Pdf displayed in browser embedded. This approach will be a great help if you have specify requirement for printing involving the layout, breaks and header/footer.



image

Monday, July 18, 2011

SSRS Record & Play testing

In my previous article I wrote about SSRS performance measurement. This time we will take a look at how we can make use of this data for our performance testing itself.

To test we would need the report, report path and the parameters; all of these we can get from the report server itself

Select catalog.name, [Catalog].Path,
ExecutionLog.Parameters
from ExecutionLog with (nolock)
inner join
Catalog on Catalog.ItemID= ExecutionLog.ReportID


This is like our manual tests being recorded, lets see how we can use this for replaying this rest.



As you know, we can access SSRS reports directly from  the server using reportServer web service URL. Using this URL we can pass query strings too!



<iframe height="100px" width=100%" src="http://172.16.150.29/ReportServer/Pages/ReportViewer.aspx?#ReportPath/ReportName#&amp;rs:Command=Render&amp;#Parameters#"/>


Use excel to import the results and use =CONCATENATE(A2,B2,C2,D2,"""/>")  in excel to generate this HTML code. Now copy these line and place it between HTML tags and your page which can open all reports in one go is ready.



Open this HTML page from multiple machines or tabs; so that it generates sufficient load. Use report server ExecutionLog view to measure the performance of your test.


Monday, July 11, 2011

How bad is your SSRS report performance?

In SSRS, the execution data is stored in a table called ExecutionLogStorage table in ReportServer database. You can view this data using the views provided by SSRS named ExecutionLog3, 2 and ExecutionLog. All these views read the data from same table, with only difference is that they interpret data and give you different views.

Following query will give you data on which report sucks.

use ReportServer
go
-- overall suckers
Select Catalog.Name,
TimeDataRetrieval+TimeProcessing+TimeRendering as TotalTime,
ExecutionLog.Format, ExecutionLog.[Parameters],
ExecutionLog.TimeDataRetrieval,
ExecutionLog.TimeProcessing, TimeRendering,
TimeStart, TimeEnd, Status, ByteCount, ExecutionLog.[RowCount]
from ExecutionLog with (nolock)
inner join Catalog on Catalog.ItemID= ExecutionLog.ReportID
order by TotalTime DESC

-- Query sucks
Select Catalog.Name,
TimeDataRetrieval+TimeProcessing+TimeRendering as TotalTime,
ExecutionLog.Format, ExecutionLog.[Parameters],
ExecutionLog.TimeDataRetrieval,
ExecutionLog.TimeProcessing, TimeRendering,
TimeStart, TimeEnd, Status, ByteCount, ExecutionLog.[RowCount]
from ExecutionLog with (nolock)
inner join Catalog on Catalog.ItemID= ExecutionLog.ReportID
order by TimeDataRetrieval DESC

-- SSRS Processing sucks
Select Catalog.Name,
TimeDataRetrieval+TimeProcessing+TimeRendering as TotalTime,
ExecutionLog.Format, ExecutionLog.[Parameters],
ExecutionLog.TimeDataRetrieval,
ExecutionLog.TimeProcessing, TimeRendering,
TimeStart, TimeEnd, Status, ByteCount, ExecutionLog.[RowCount]
from ExecutionLog with (nolock)
inner join Catalog on Catalog.ItemID= ExecutionLog.ReportID
order by TimeProcessing DESC

-- SSRS Rendering sucks
Select Catalog.Name,
TimeDataRetrieval+TimeProcessing+TimeRendering as TotalTime,
ExecutionLog.Format, ExecutionLog.[Parameters],
ExecutionLog.TimeDataRetrieval,
ExecutionLog.TimeProcessing, TimeRendering,
TimeStart, TimeEnd, Status, ByteCount, ExecutionLog.[RowCount]
from ExecutionLog with (nolock)
inner join Catalog on Catalog.ItemID= ExecutionLog.ReportID
order by TimeProcessing DESC

Friday, October 15, 2010

Error:Microsoft.ReportingServices.Diagnostics.Utilities.SecureConnectionRequiredException: The operation you are attempting requires a secure connection (HTTPS)

I had this problem from long time and was in such a urgency that i started working with HTTPS. But finally i had to move my machine out of the domain, and left with only option of fixing it.

First step i did was went to “C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\LogFiles”, which you have already figured out i guess. At the latest log file, you will see this error listed. Which means that RS is configured only for HTTPS and not for HTTP.

To resolve… lets change it.

For not using SSL you need to modify following section in reportserver.config file, at C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer and change

<Add Key="SecureConnectionLevel" Value="2"/>




entry with value from 2 to “0”

Monday, June 21, 2010

Hosting Silverlight Application on Facebook

Objective is to create a game using Silverlight which will utilize Facebook platform and publish on facebook application directory. Following are the features which we will target to deliver
  1. You can compare your score with friends
  2. You can invite your friends on Facebook
  3. You can post your score and events like beating a friend on to your wall
  4. List top 100 scores
  5. List your friends top score along with their profile pictures
In simple words, we are going to walk through the creation of ittiGator Game on Facebook. Take a break now, have a good look at it and come back. Here you go… http://apps.facebook.com/ittigator
Creating game using Silverlight
I will not go into details, its left to your creativity and coding to create a working model. Make sure you make it modular, and lets make a module called ScoreCard and place a control called ScoreCardControl. Here we will list out 6 users including the player , ordered by scores. What you would need from Facebook will be friends list, and friend’s photo. Scores we will be maintained in our SQL Server DBs

To be continued...

Friday, January 15, 2010

Deadlock!!! ..and getting out of it.

Its easy to create deadlocks in SQL, just one slip in your code and lot of load on your script makes the ideal condition for deadlock to occur.
Microsoft believes you, have lot of faith in you. So it offers tools to resolve and rescue from your coding disaster.

Say you have a deadlock, show it. Find how you can reproduce this, unless you know how to reproduce it, you will never be sure of your fix; well, like always.

First thing to do once you see a deadlock is, extract the deadlock trace data. To do so, you can set flags in SQL by running following command
dbcc traceon (1204, 3605, 1222, -1)
This flag is set only for current session of SQL server, if you restart the SQL you need to redo it. You can also set this flag as startup parameter by adding –T1222 in SQL server properties dialog.
When deadlock occurs, you can see the DB log to contain the most of the information. I have found graph drawn by the profiler as more useful than the log.

This graph you can view in profiler and you can store as XML. This XML has all the information that can give you a lead. XDL – ie XML representation of Deadlock graph has information like
1) Procedures involved
2) Line number involved in deadlock
3) Script line involved
4) Data involved
5) Victim thread, SQL terminates one process to break the deadlock
6) Mode of lock on the resource
Most of the cases this information would be sufficient to get you out of it.

Common solutions:
1) Consider rearranging the script so that you isolate all different operations like select, delete, insert and update. Make sure you have same pattern in both the scripts who are involved in deadlock. Say delete first, select next then you do a insert in both the stored procedures.
2) Un-clustered indexes adds overhead of updating indexes which require exclusive locks and if select is also running on table, then there is a possibility of deadlock. Making the clustered index can resolve the problem.
3) Run the Query analyzer and see the execution graph. You can see the pattern of two scripts running and see the overlap. This could give you fair idea on what could be going wrong, or gives the idea on possibilities.

Now you are on your own…
Posted by Picasa

Saturday, August 8, 2009

Compare SQL Databases

If you ever come across a situation where your application behaves differently with different DBs you have and not sure if any of the Stored procedures have changed...?
Following SQL script can be used to compare the Stored procedures.
select top SYSCOM_1.text, DB2.text 
from MyDATABASE_1.dbo.syscomments SYSCOM_1 
inner join 
sysobjects so on so.id=SYSCOM_1.id inner join 
(select SYSCOM_2.text,SYSCOM_2.id, so.name from MyDATABASE_2.dbo.syscomments SYSCOM_2inner join MyDATABASE_2.dbo.sysobjects so on so.id=SYSCOM_1.id )
DB2 on so.name = DB2.name COLLATE DATABASE_DEFAULT 
where DB2.text <> SYSCOM_1.text COLLATE DATABASE_DEFAULT