Archive

Posts Tagged ‘SQL Server’

Implementing Paging in SQL Server 2005 Stored Procedures

April 29th, 2010 Anuraj P No comments

Normally for implementing Paging in Grid View, we enable the Paging property in GridView and will write code in the PageIndex Changed event. But the problem with this approach is it will fetch all the data from Database for Paging, will result wastage of network bandwidth and resources, also affect in the Page Performance. In SQL Server 2005 Microsoft introduced a new concepts called Row_Number() and Derived Table with the help these two we can move the Paging logic to Database instead of ASP.Net web forms. This concept also works with custom paging implementations for DataList or Repeater controls.

CREATE PROCEDURE usp_GetContacts
(@Page INT, @RecsPerPage INT)
AS
SELECT tblContacts.[Name], tblContacts.[IsParent] FROM
(SELECT ROW_NUMBER() OVER(ORDER BY [ID]) AS RowNumber,
[Name], [IsParent] FROM [TreeView].[dbo].[Contacts]) tblContacts
WHERE RowNumber > @RecsPerPage*(@Page) AND RowNumber <= @RecsPerPage*(@Page+1)

In this code we are creating a Column called “RowNumber”. And we are comparing the input parameters with the derived table tblContacts.

Thanks to Aneesh / Prasanth for their valueable suggestions and comments.

Enumerating Instances of SQL Server using C#

December 18th, 2009 Anuraj P No comments

One of the project I am worked, I had to enumerate SQL Server instances of the network for creating dynamic connection string. Here is a code snippet which will retrieve all the SQL Server instance in a network using C# and ADO.Net.

using System.Data;
using System.Data.Sql;

SqlDataSourceEnumerator sqlDataSourceEnumerator = SqlDataSourceEnumerator.Instance;
DataTable sqlServerInstances = sqlDataSourceEnumerator.GetDataSources();

The Data Table contains 4 columns, and columns are

  1. ServerName - Name of the Server.
  2. InstanceName - Name of the server instance. Blank if the server is running as the default instance.
  3. IsClustered - Indicates whether the server is part of a cluster.
  4. Version - Version of the server (8.00.x for SQL Server 2000, 9.00.x for SQL Server 2005, and 10.0.x for SQL Server 2008).

Another way is using SQL Server Management Objects (SMO). For this you need to add reference of Microsoft.SqlServer.Smo assembly.

DataTable sqlServerInstances = SmoApplication.EnumAvailableSqlServers();

It will also return a Data Table, with 6 columns and the columns are

  1. Name- Name of the Server.
  2. Server - The name of the server on which the instance of SQL Server is installed.
  3. Instance-The instance of SQL Server.
  4. IsClustered -A Boolean value that is True if the instance is participating in failover clustering, or False if it is not.
  5. Version -Version of the SQL Server (8.00.x for SQL Server 2000, 9.00.x for SQL Server 2005, and 10.0.x for SQL Server 2008).
  6. IsLocal-A Boolean value that is True if the instance is local, or False if the instance is remote.
Categories: .Net, ASP.Net, SQL Server Tags: , , , ,

Implementing Custom Paging in DataRepeater using C# and SQL Server

October 22nd, 2009 Anuraj P No comments

Normally DataRepeater doesn’t have a paging feature; and you can implement it using LINQ, if you are using .Net 3.5. Here is an implementation which is using SQL Server 2005 feature ROW_NUMBER(). You can get more information about ROW_NUMBER() from MSDN.

Stored Procedure – xsp_GetPersons

CREATE PROCEDURE xsp_GetPersons
@StartIndex INT, @Count INT
AS
BEGIN
DECLARE @EndIndex INT
SET @StartIndex = @StartIndex * @Count
SET @EndIndex = @StartIndex + @Count
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY UserId DESC) AS SlNo, UserId, FirstName, LastName, Email, ISNULL(DOB, GETDATE()) AS DOB FROM U_MyRegistration)Registration WHERE Registration.SlNo BETWEEN @StartIndex AND @EndIndex
END

And I added a DataRepeater control, with Next and Previous buttons in the Footer.

<tr>
    <td colspan="3" align="left">
        <asp:LinkButton CommandName="Navigation" CommandArgument="Prev" runat="server" ID="linkPrevious"
            Text="<< Previous" />
    </td>
    <td colspan="3" align="right">
        <asp:LinkButton CommandName="Navigation" CommandArgument="Next" runat="server" ID="linkNext" Text="Next >>" />
    </td>
</tr>

Code behind. As it is a sample code, I am not added any validations.

int count = 10;
protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        BindData(); //Binding Data.
    }
}

private void BindData()
{
    int startIndex = Convert.ToInt32(this.hidCurrentIndex.Value);
    Persons p = new Persons();
    this.Repeater1.DataSource = null;
    this.Repeater1.DataSource = p.GetPersons(startIndex, count);
    this.Repeater1.DataBind();
}

protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
    if (e.CommandName.Equals("Navigation",
StringComparison.CurrentCultureIgnoreCase))
    {
        if (e.CommandArgument.ToString().Equals("Prev",
StringComparison.CurrentCultureIgnoreCase))
        {
            this.hidCurrentIndex.Value = (Convert.ToInt32
(this.hidCurrentIndex.Value) - 1).ToString(); //Decrementing the count
            this.BindData();
        }
        else
        {
            this.hidCurrentIndex.Value = (Convert.ToInt32
(this.hidCurrentIndex.Value) + 1).ToString(); //Incrementing the count
            this.BindData();
        }
    }
}

And the implementation of Persons class from App_Code

using System;
using System.Collections.Generic;
using System.Data.SqlClient;

public class Persons : List<Persons.Person>
{
    public class Person
    {
        public int UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public DateTime DOB { get; set; }
    }

    public Persons GetPersons(int startIndex, int count)
    {
        Persons persons = new Persons();
        using (SqlConnection connection = new SqlConnection ("Server=.\SQLEXPRESS;User Id=sa;Password=sapwd;Database=myDatabase"))
        {
            connection.Open();
            using (SqlCommand command = new SqlCommand("xsp_GetPersons",

connection))
            {
                command.CommandType = System.Data.CommandType.StoredProcedure;
                command.Parameters.AddWithValue("@StartIndex", startIndex);
                command.Parameters.AddWithValue("@Count", count);
                SqlDataReader reader = command.ExecuteReader();
                while (reader.Read())
                {
                    persons.Add(new Person()
                    {
                        DOB = Convert.ToDateTime(reader["DOB"].ToString()),
                        Email = reader["Email"].ToString(),
                        FirstName = reader["FirstName"].ToString(),
                        LastName = reader["LastName"].ToString(),
                        UserId = Convert.ToInt32(reader["UserId"].ToString()),
                    });
                }
            }
        }
        return persons;
    }
}

The core thing is stored procedure, which will return the results based on the given index. Thanks to Aneesh for the details of ROW_NUMBER() function.

How to Store and Retrieve files from SQL Server Database

October 7th, 2009 Anuraj P No comments

The forum I joined recently got lot of queries like How to Save Images in the Database, How to save files in SQL Server, How read files from Database etc. So I thought of writing a post regarding this. Even though I am part of a Web project, I am doing some Windows applications for the client. So I thought it will nice to brush-up the ASP.Net skills.

Here is the code. I am using SQL Server 2008, but I am not using FileStream for the current project, I already wrote a post to how to
manage files with FileStream feature. In this post I am using nvarchar(MAX) datatype for storing the file content.

Table Design

CREATE TABLE [dbo].[tblFiles](
	[FileId] [uniqueidentifier] NOT NULL,
	[Filename] [nvarchar](255) NOT NULL,
	[FileContent] [varbinary](max) NULL
)

And the I set FileId default to newId() and FileContent default to NULL

ALTER TABLE [dbo].[tblFiles] ADD  CONSTRAINT [DF_tblFiles_FileId]  DEFAULT (newid()) FOR [FileId]
GO
ALTER TABLE [dbo].[tblFiles] ADD  CONSTRAINT [DF_tblFiles_FileContent]  DEFAULT (NULL) FOR [FileContent]
GO

I wrote the code in C#. I am having a Asp FileUpload control and a button to upload the file, and a Repeater control with two controls, a label for displaying the filename and hyper link control for downloading the file.

<body>
<form runat="server">
<asp:FileUpload runat="server" ID="fileUploadImage" />
<asp:Button runat="server" ID="cmdUpload" Text="Upload File" OnClick="cmdUpload_Click" />
<asp:Repeater runat="server" ID="rptrFiles">
    <HeaderTemplate>
        <table>
    </HeaderTemplate>
    <ItemTemplate>
        <tr>
            <td>
                <asp:Label runat="server" ID="lblFilename" Text='<%# Eval("FileName")%>' />
            </td>
            <td>
              <asp:HyperLink runat="server" Target="_blank" ID="lbtDownload" Text="Download" NavigateUrl='<%# "Download.aspx?File="  + Eval("FileId").ToString() %>' />
            </td>
        </tr>
    </ItemTemplate>
    <FooterTemplate>
        </table>
    </FooterTemplate>
</asp:Repeater>
</form>
</body>

Uploading the File to the Database
Code behind

protected void cmdUpload_Click(object sender, EventArgs e)
{
    string fileName = Path.GetFileName(this.fileUploadImage.FileName);
    byte[] fileContent = this.fileUploadImage.FileBytes;
    using (SqlConnection connection = new SqlConnection("Server=.\\SQLEXPRESS;User Id=sa;Password=sapassword;Database=sampledb"))
    {
        connection.Open();
        using (SqlCommand command = new SqlCommand("INSERT INTO tblFiles(Filename, FileContent) VALUES(@Filename, @FileContent)", connection))
        {
            SqlParameter fileNameParameter = new SqlParameter("@Filename", System.Data.SqlDbType.NVarChar, 255);
            fileNameParameter.Value = fileName;
            SqlParameter fileContentParameter = new SqlParameter("@FileContent", System.Data.SqlDbType.VarBinary);
            fileContentParameter.Value = fileContent;
            command.Parameters.AddRange(new SqlParameter[] { fileNameParameter, fileContentParameter });
            command.ExecuteNonQuery();
        }
    }
}

And here is code to bind the repeater from the Database

DataTable dtFiles = new DataTable("Files");
using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT FileId, FileName FROM tblFiles", "Server=.\\SQLEXPRESS;User Id=sa;Password=sapassword;Database=sampledb"))
{
    adapter.Fill(dtFiles);
}
this.rptrFiles.DataSource = dtFiles;
this.rptrFiles.DataBind();

Download / Read the file from Database
And to download / read the file from Database, I am passing the File unique id to another page(download.aspx).I this page I am checking for the File querysting and based on that reading filecontent from Sql and writing it to Asp.net output stream. You can get more information about how to download files from IIS in this post.

protected void Page_Load(object sender, EventArgs e)
{
    if (Request.QueryString["File"] != null)
    {
        string fileId = Request.QueryString["File"];
        using (SqlConnection connection = new SqlConnection("Server=.\\SQLEXPRESS;User Id=sa;Password=sapassword;Database=Sample"))
        {
            connection.Open();
            using (SqlCommand command = new SqlCommand("SELECT Filename, FileContent FROM tblFiles WHERE FileId = @FileId", connection))
            {
                command.Parameters.AddWithValue("@FileId", fileId);
                SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
                if (reader.HasRows)
                {
                    reader.Read();
                    byte[] content = reader["FileContent"] as byte[];
                    string filename = reader["FileName"].ToString();
                    Response.Clear();
                    Response.ClearContent();
                    Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
                    Response.AddHeader("Content-Length", content.Length.ToString());
                    Response.OutputStream.Write(content, 0, content.Length);
                    Response.End();
                }
            }
        }
    }
}

Please write to me if I missed something. Happy Programming .

Import / export data in MS Excel using C#

September 23rd, 2009 Anuraj P No comments

Sometimes we may require to generate Excel file from our reports,read from excel files to import data etc. This can be achieved using Office Interop (Office Automation) assemblies, but Office Automation in Web servers,got some issues;(More details: http://support.microsoft.com/kb/257757). The alternative is using OleDb provider. You may need to add one more attribute to connection string to connect to the Excel file. And connection string will be

string connectionString = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=C:\Sample.xls; Extended Properties=Excel 8.0;"

Please note the “Extended Properties” attribute. This attribute helps us to query the excel file.

Exporting Data from Data Table to Excel File.

string connectionString = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=C:\Sample.xls; Extended Properties=Excel 8.0;"
// Establish a connection to the data source.
using(OleDbConnection Connection = new OleDbConnection(connectionString))
{
Connection.Open()
//creating a new Sheet with name sample and three columns with Heading firstname, lastname and email
using(OleDbCommand command = new OleDbCommand())
{
command.Connection = Connection;
command.CommandText = "CREATE TABLE [Sample$](FirstName Char(255), LastName char(255), Email char(255))";
command.ExecuteNonQuery();
}
//Adding records to the Sample Worksheet
using(OleDbCommand command = new OleDbCommand())
{
command.Connection = Connection;
command.CommandText = "INSERT INTO TABLE [Sample$](FirstName,LastName,Email) VALUES('Anuraj','P','anuraj.p@example.com')";
command.ExecuteNonQuery();
command.CommandText = "INSERT INTO TABLE [Sample$](FirstName,LastName,Email) VALUES('sreekumar','vn','sreekumar.vn@example.com')";
command.ExecuteNonQuery();
}
}

Import the Data from Excel

DataTable dt;
string connectionString = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=C:\Sample.xls; Extended Properties=Excel 8.0;"
// Establish a connection to the data source.
using(OleDbConnection Connection = new OleDbConnection(connectionString))
{
Connection.Open()
//reading data from excel to Data Table
using(OleDbCommand command = new OleDbCommand())
{
command.Connection = Connection;
command.CommandText = "SELECT * FROM [Sample]";
using(OleDbDataAdapter adapter =new OleDbDataAdapter())
{
adapter.SelectCommand = command;
adapter.Fill(dt);
}
}
}

You can get more information from Microsoft support site

http://support.microsoft.com/kb/306023 – How to transfer data to an Excel workbook by using Visual C# 2005 or Visual C# .NET

Adding and Reading files from SQL Server 2008 Filestream

September 22nd, 2009 Anuraj P No comments

Few days back I wrote a Post about FileStream feature in SQL 2008.(Filestream in SQL Server 2008). In this post I am trying to write the how to manage or use the FileStream feature from .Net managed code.

For adding a File to FileStream enabled table, we are using a new Data Type, SqlFileStream, which comes with .Net 3.5.

I am using the Table structure as in the Previous post, as the example, that Table contains 3 columns, FileID(PK), FileName and FileContents.
For inserting a File you need to begin a transaction, insert an row in to the Table, without the contents of the File, for reading the Transaction context. Then using FileStream, write the contents of the File to the Row. After writting the stream, need to commit the transaction to update the file to the Database. I am writing the code in VB.Net.

Code for saving the File to the Database

Private Sub AddFile(ByVal fileName As String)
	Dim _Transaction As SqlTransaction
	Dim _Command As SqlCommand
	Dim _DataReader As SqlDataReader
	Dim _Connection As SqlConnection
	Dim _FileId As String
	Dim _FilePath As String
	Dim _FileNameParameter As SqlParameter
	Dim _FileIdParameter As SqlParameter
	Dim _FilePathParameter As SqlParameter

	Dim _SQLFileStream As SqlTypes.SqlFileStream
	Dim _Context As Byte()

	Try
		_Connection = New SqlConnection("Server=.\SQL2008;Integrated Authentication=SSPI;Database=FileSystemExample;")
		_Connection.Open()
		_Transaction = _Connection.BeginTransaction()
		_Command = New SqlCommand("xsp_InsertFile", _Connection, _Transaction)
		_Command.CommandType = CommandType.StoredProcedure
		_Command.Parameters.AddRange(New Object() {_FileIdParameter, _FileNameParameter, _FilePath})
		_FileId = Guid.NewGuid().ToString

		_FileIdParameter = New SqlParameter("@FileId", SqlDbType.UniqueIdentifier)
		_FileIdParameter.Value = _FileId

		_FileNameParameter = New SqlParameter("@FileName", SqlDbType.VarChar)
		_FileNameParameter.Value = fileName

		_FilePathParameter = New SqlParameter("@FilePath", SqlDbType.VarChar)
		_FilePathParameter.Direction = ParameterDirection.Output

		_DataReader = _Command.ExecuteReader(CommandBehavior.SingleRow)
		If _DataReader.HasRows Then
			_FilePath = _DataReader("FilePath").ToString
		End If
		If Not _DataReader.IsClosed Then
			_DataReader.Close()
		End If

		_Command = New SqlCommand("SELECT GET_FILESTREAM_TRANSACTION_CONTEXT() FROM SQLFileSystem", _Connection, _Transaction)
		_Context = _Command.ExecuteScalar()

		_SQLFileStream = New SqlFileStream(_FilePath, _Context, FileAccess.Write)
		_SQLFileStream.Write(_Context, 0, _Context.Length)
		_SQLFileStream.Close()

		_Transaction.Commit()
	Catch ex As Exception
		If _Transaction IsNot Nothing Then
			_Transaction.Rollback()
		End If
	Finally
		If _Connection IsNot Nothing Then
			_Connection.Close()
		End If
	End Try
End Sub

Code for reading the File from the Database

Private Function ReadFile(ByVal fileId As String) As Byte()
	Dim _Transaction As SqlTransaction
	Dim _Command As SqlCommand
	Dim _DataReader As SqlDataReader
	Dim _Connection As SqlConnection
	Dim _FilePath As String
	Dim _FileIdParameter As SqlParameter

	Dim _SQLFileStream As SqlTypes.SqlFileStream
	Dim _Context As Byte()

	Try
		_Connection = New SqlConnection("Server=.\SQL2008;Integrated Authentication=SSPI;Database=FileSystemExample;")
		_Connection.Open()
		_Transaction = _Connection.BeginTransaction()
		_Command = New SqlCommand("SELECT FileStreamData.PathName() AS [FilePath],GET_FILESTREAM_TRANSACTION_CONTEXT() AS [Context] FROM SQLFileSystem WHERE FileId=@FileId", _Connection, _Transaction)
		_Command.CommandType = CommandType.StoredProcedure

		_FileIdParameter = New SqlParameter("@FileId", SqlDbType.UniqueIdentifier)
		_FileIdParameter.Value = fileId
		_Command.Parameters.Add(_FileIdParameter)

		_DataReader = _Command.ExecuteReader(CommandBehavior.SingleRow)
		If _DataReader.HasRows Then
			_FilePath = _DataReader("FilePath").ToString()
			_Context = TryCast(_DataReader("Context"), Byte())
		End If

		_SQLFileStream = New SqlFileStream(_FilePath, _Context, FileAccess.Read)
		_SQLFileStream.Read(_Context, 0, _Context.Length)
		_SQLFileStream.Close()

		_Transaction.Commit()
	Catch ex As Exception
		If _Transaction IsNot Nothing Then
			_Transaction.Rollback()
		End If
	Finally
		If _Connection IsNot Nothing Then
			_Connection.Close()
		End If
	End Try
	Return _Context
End Function

Stored Procedure

CREATE PROCEDURE xsp_InsertFile
(
@FileName VARCHAR(255),
@FileId UNIQUEIDENTIFIER,
@FilePath VARCHAR(MAX) OUTPUT)
AS
BEGIN
SET NOCOUNT OFF
INSERT INTO SQLFileSystem (FileId, FileName) VALUES(@FileId, @FileName)
SELECT @FilePath = SystemFile.PathName() from SQLFileSystem where FileId = @FileId
END

Note: I didn’t tested the code. Please let me know if you found any issues in the implementation.