Accessing File-Stream Data Methods (T-SQL and Managed API) - tsql

I have "File-Stream" enabled database. I have created table with column that has the "file-stream" attribute and manage to record successfully row in the table. So, what I have got is image stored in my "File-Stream" as BLOB.
What is my problem?
I have to get this image and show it in the web browser using classic asp (I am total newbie in this server-language and I am not allowed to use the asp.net). I have searched and read a lot (there are many information about doing that with asp.net and almost nothing showing how to do this with classic asp) and found a article (http://www.simple-talk.com/sql/learn-sql-server/an-introduction-to-sql-server-filestream/) that shows to ways to read the data:
"Accessing FILESTREAM Data using TSQL" and "Accessing FILESTREAM data with Managed API"
The first one I have been able to understand and use. The second one (there is a example with vb.net code) I haven't been able.
This is the code:
‘Create a connection to the database
Dim ConStr As String
ConStr = "Data Source=JACOBXPS\katmaifs;Initial Catalog=NorthPole" & _
";Integrated Security=True"
Dim con As New SqlConnection(ConStr)
con.Open()
'Retrieve the FilePath() of the image file
Dim sqlCommand As New SqlCommand()
sqlCommand.Connection = con
sqlCommand.CommandText = "SELECT ItemImage.PathName() AS PathName " + _
"FROM items WHERE ItemNumber = 'MS1001'"
Dim filePath As String = sqlCommand.ExecuteScalar()
'Obtain a Transaction Context
Dim transaction As SqlTransaction = con.BeginTransaction("ItemTran")
sqlCommand.Transaction = transaction
sqlCommand.CommandText = "SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()"
Dim txContext As Byte() = sqlCommand.ExecuteScalar()
' Open and read file using SqlFileStream Class
Dim sqlFileStream As New SqlFileStream(filePath, txContext, FileAccess.Read)
Dim buffer As Byte() = New Byte(sqlFileStream.Length) {}
sqlFileStream.Read(buffer, 0, buffer.Length)
'Bind the image data to an image control
Dim ms As MemoryStream = New MemoryStream(buffer)
Dim bmp As Bitmap = New Bitmap(ms)
ItemImage.Image = bmp
'Cleanup
sqlFileStream.Close()
sqlCommand.Transaction.Commit()
con.Close()
I was not able to transform this in classic asp but in the same article I have read something more frustrating:
When accessing FILESTREAM data using TSQL, SQL Server reads the content of the >FILESTREAM data file and serves it to the client. SQL Server memory is used for reading >the content of the data file. Accessing FILESTREAM data using Win32 Streaming does not >use SQL Server memory. In addition it allows the application to take advantage of the >Streaming capabilities of the NT File System.
So what is my real problem?
Can be the vb.net code transform and used in a classic asp?And if it can, does that mean that when I am using the "file-stream" enable futures and want to display data in the web it will be more slow then using desktop application?
I am pretty confused and will appreciate any answer or link with article to read.

A little confused on the question but if all you're trying to do is display some BLOB data from the database as an Image on the webpage then you should have an "image.asp" page that looks something like this ...
SQL = "SELECT FILE_NAME,IMAGE_FILE FROM tblImages WHERE ID = " & request("id")
Set rs =db.Execute( SQL )
if not(rs.eof) then
Response.ContentType = "application/octet-stream"
Response.AddHeader "Content-Disposition", "attachment;filename=" & rs("FILE_NAME")
Response.BinaryWrite rs("IMAGE_FILE")
else
response.Write("No such record found in the database at row " & request("id"))
end if

Related

Crystal reports - server and database

Im using visual studio 2010 + Sql Server 2008.
Im trying to show my reports using CR.. well when i try to use the system in my local machine, everything is ok.
I use store procedures to create reports.
The issue appears when i deploy the system in another PC.. A message appears asking for:
Server: // RETRIEVES ORIGINAL Server(Local)// Its not Correct i need to get Client Server
Database: // RETRIEVES ORIGINAL DB(Local)// Its not Correct i need to get Client DB
Username: I don't use any user , what user ?
Password: I don't use any password, what password?
i saw another solutions, but i can't find what's the data that i must use in Username or password. i use Windows autenthication to login to sql..
Thanks.
Regards.
Edit.. that's my code.. i can't use parameters, i don't receive any error. but system dont recognize the parameter that i send...
Dim NuevoReporte As New CReportNotaPorUsuario
Dim contenido As String
Dim ReportPath As String = My.Application.Info.DirectoryPath & "\CReportNotaPorUsuario.rpt"
Dim ConexionCR As New CrystalDecisions.Shared.ConnectionInfo()
contenido = Servicios.Funciones_Auxiliares.LeerArchivo(My.Application.Info.DirectoryPath & "\configuracion.txt")
ConexionCR.ServerName = Servicios.Funciones_Auxiliares.TextoEntreMarcas(contenido, "<server>", "</server>")
ConexionCR.DatabaseName = Servicios.Funciones_Auxiliares.TextoEntreMarcas(contenido, "<catalog>", "</catalog>")
ConexionCR.IntegratedSecurity = True
CrystalReportViewer1.ReportSource = ReportPath
'NuevoReporte.SetParameterValue("#cod_usuario", cbousuario.SelectedValue)
Dim field1 As ParameterField = Me.CrystalReportViewer1.ParameterFieldInfo(0)
Dim val1 As New ParameterDiscreteValue()
val1.Value = cbousuario.SelectedValue
field1.CurrentValues.Add(val1)
SetDBLogonForReport(ConexionCR)
It appears that you have separate servers and databases between the development and production environment. You need to make sure when you deploy your VS solution that the production server and database get referenced, not the development server and database.
There are some tutorials out there that can help you find a way to achieve this. Check out:
http://msdn.microsoft.com/en-us/library/dd193254(v=vs.100).aspx
Visual Studio 2010 Database Project Deploy to Different Environments
http://www.asp.net/web-forms/tutorials/deployment/advanced-enterprise-web-deployment/customizing-database-deployments-for-multiple-environments
EDIT: This seems to have evolved into a different issue than originally stated in the question. To dynamically get the connection string for CR from the text file, you will have to read teh text file first and put server name and database name into variables. Reading a text file, you can use something like string text = File.ReadAllText(#"C:\Folder\File.txt"); but you will need to extract server name and database name into variables. Then in order to use the variables in your connection string you use ConnectionInfo.Servername = variable1; and ConnectionInfo.DatabaseName = variable2.

Run a Stored Procedure via a click of a button in .Net web page

Afternoon All,
I have a stored procedure in an SQL 2005 database named GasNominationsRawData_Insert.
When executed this simply extracts some data from another database and inserts the result into a table. This query works fine.
What i need to do is enable this to be executed on the click on a button on my web page. I have had a good luck around the internet have have managed to create the following code in my .net 2008 web page. But i think im either missing something or i have have completly the wrong code. Im new to programming in .Net but i understand that i need to delclare the stored procedure, create the SQL connection, create the command line, open the conection, execute the query and then close the connection.
I dont need or have any parameters. Essentially this button is just used to push data to a table.
Imports System.Data
Imports System.Data.SqlClient
Partial Class RawData
Inherits System.Web.UI.Page
Protected Sub btnAddRawData_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddRawData.Click
'Declare Stored Procedure
Dim GasNominationsRawData_Insert As String = "GasNominationsRawData_Insert"
'Declare SQL Connection (This is the connection string located on the web.config page)
Dim SQLConn As SqlConnection
SQLConn = New SqlConnection("GasNominationsDataConnectionString")
'Declare command
Dim SqlComm As SqlCommand = New SqlCommand("GasNominationsRawData_Insert", SQLConn)
SqlComm.CommandType = CommandType.StoredProcedure
Try
'Open SQL Connection
SQLConn.Open()
'Execute Query
SqlComm.ExecuteNonQuery()
'Close connection
SQLConn.Close()
Catch ex As Exception
Throw (ex)
End Try
End Sub
End Class
Any Help is much appreciated.
Regards Betty
Upps. I overlooked that. You're trying to connect to your database with the connectionstring: "GasNominationsDataConnectionString". That's of course no correct connection string.
Your connection string should look somehow like that:
"Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;"
So you have to get your connection string first out of your web.config like
Dim GasNominationsDataConnectionString As String = ConfigurationManager.ConnectionStrings("GasNominationsDataConnectionString").ConnectionString
Regards
Anja
Looks fine at a first glance. So what happens on clicking the button? Have you assured that your btnAddRawData_Click is called when the button is clicked?

How to read an .XLSX (Excel 2007) file using ADO.NET? I am finding "Could not find installable ISAM"-error

I need to work in .net 2.0. So I can't use OpenXML.
This is my source code and I have already Installed AccessDatabaseEngine.exe.
But still getting the exception:
"Could not find installable ISAM".
I have also tried "Extended Properties=Excel 8.0" in the connection string.
static void Main(string[] args)
{
DataSet dataSet = new DataSet();
OleDbConnection connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|Data Directory|\HSC.xlsx;Extended Properties=Excel 12.0;HDR=YES;");
OleDbDataAdapter dataAdapter= new OleDbDataAdapter("select * from [Sheet1$]", connection);
dataAdapter.Fill(dataSet);
}
According to Carl Prothman, that should be
Extended Properties="Excel 12.0 Xml;
-- http://www.connectionstrings.com/excel-2007
In more detail:
OleDbConnection connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Docs\\Book2.xlsx;Extended Properties='Excel 12.0 xml;HDR=YES;'");
Note the single quotes.
I prefer to use the Microsoft OpenXML 2.0 SDK for this kind of functionality. It has a really nice interface, and it does not put a demand on having Office installed on the machine reading the XLSX file which is a good thing.
I'm writing this from my mobile, so hard to provide a link, but a Google search should easily find it for you.
Give it a try. I think you will like it.
EDIT
If you have to use .NET 2.0, you can go for using the JET variant of the OleDb instead.
That means you will do something like this to connect:
OleDbConnection connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source='" + filename + "';" +
"Extended Properties=\"Excel 8.0;HDR=No;IMEX=1;\"";);
Then you can query it like in your example above:
OleDbDataAdapter objAdapter = new OleDbDataAdapter("select * from [Sheet1$]", connection);
Try it! Just note that Jet have some strange logic of deciding if a column is numeric or not. See the following SO questions for details: Problem with using OleDbDataAdapter to fetch data from a Excel sheet
You should make sure that the connection string looks like the following ( even if you are accessing microsoft excel version 10 ->
MyConnection = new System.Data.OleDb.OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;
Data Source='D:\csharp-Excel.xls';Extended Properties='Excel 12.0 Xml;HDR=Yes;'");

excel to xml conversion using ado

How to convert excel data into xml file using ado.net?
You can use the Microsoft Jet OLEDB 4.0 Data Provider to read the Excel file. Information about how to establish a connection to an Excel file can be found here.
This article explains how to read an Excel file using the provider. Once you have read the data, you can compose your XML document using LINQ to XML or the System.Xml classes.
In Excel, you can save the file to XML by using the File menu and changing the saved file type to XML spreadsheet.
If you want to read an Excel XML file with ADO.Net, try the XmlReader.
Or see this step-by-step example from Microsoft.
I've not used ado.net, but I've used xquery very successfully for this. Use excel export to create an XML file, then write xquery/xpath commands to convert as you want. Excel XML export format is pretty gnarly but it does do the job. Use the Oxygen 30 day eval license to lighten the xquery debug job.
use this code :
public static DataSet exceldata(string filelocation)
{
DataSet ds = new DataSet();
OleDbCommand excelCommand = new OleDbCommand();OleDbDataAdapter excelDataAdapter = new OleDbDataAdapter();
string excelConnStr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + filelocation + "; Extended Properties =Excel 8.0;";
OleDbConnection excelConn = new OleDbConnection(excelConnStr);
excelConn.Open();
DataTable dtPatterns = new DataTable();excelCommand = new OleDbCommand("SELECT UUID, `PATTERN` as PATTERN, `PLAN` as PLAN FROM [PATTERNS$]", excelConn);
excelDataAdapter.SelectCommand = excelCommand;
excelDataAdapter.Fill(dtPatterns);
dtPatterns.TableName = "Patterns";
ds.Tables.Add(dtPatterns);
return ds;
}
and then convert returned datatable to xml with DataTable.WriteXml()

Reporting Services Deployment

I need to create a repeatable process for deploying SQL Server Reporting Services reports. I am not in favor of using Visual Studio and or Business Development Studio to do this. The rs.exe method of scripting deployments also seems rather clunky. Does anyone have a very elegant way that they have been able to deploy reports. The key here is that I want the process to be completely automated.
We use rs.exe, once we developed the script we have not needed to touch it anymore, it just works.
Here is the source (I slightly modified it by hand to remove sensitive data without a chance to test it, hope I did not brake anything), it deploys reports and associated images from subdirectories for various languages. Also datasource is created.
'=====================================================================
' File: PublishReports.rss
'
' Summary: Script that can be used with RS.exe to
' publish the reports.
'
' Rss file spans from beginnig of this comment to end of module
' (except of "End Module").
'=====================================================================
Dim langPaths As String() = {"en", "cs", "pl", "de"}
Dim filePath As String = Environment.CurrentDirectory
Public Sub Main()
rs.Credentials = System.Net.CredentialCache.DefaultCredentials
'Create parent folder
Try
rs.CreateFolder(parentFolder, "/", Nothing)
Console.WriteLine("Parent folder created: {0}", parentFolder)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
PublishLanguagesFromFolder(filePath)
End Sub
Public Sub PublishLanguagesFromFolder(ByVal folder As String)
Dim Lang As Integer
Dim langPath As String
For Lang = langPaths.GetLowerBound(0) To langPaths.GetUpperBound(0)
langPath = langPaths(Lang)
'Create the lang folder
Try
rs.CreateFolder(langPath, "/" + parentFolder, Nothing)
Console.WriteLine("Parent lang folder created: {0}", parentFolder + "/" + langPath)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
'Create the shared data source
CreateDataSource("/" + parentFolder + "/" + langPath)
'Publish reports and images
PublishFolderContents(folder + "\" + langPath, "/" + parentFolder + "/" + langPath)
Next 'Lang
End Sub
Public Sub CreateDataSource(ByVal targetFolder As String)
Dim name As String = "data source"
'Data source definition.
Dim definition As New DataSourceDefinition
definition.CredentialRetrieval = CredentialRetrievalEnum.Store
definition.ConnectString = "data source=" + dbServer + ";initial catalog=" + db
definition.Enabled = True
definition.EnabledSpecified = True
definition.Extension = "SQL"
definition.ImpersonateUser = False
definition.ImpersonateUserSpecified = True
'Use the default prompt string.
definition.Prompt = Nothing
definition.WindowsCredentials = False
'Login information
definition.UserName = "user"
definition.Password = "password"
Try
'name, folder, overwrite, definition, properties
rs.CreateDataSource(name, targetFolder, True, definition, Nothing)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
Public Sub PublishFolderContents(ByVal sourceFolder As String, ByVal targetFolder As String)
Dim di As New DirectoryInfo(sourceFolder)
Dim fis As FileInfo() = di.GetFiles()
Dim fi As FileInfo
Dim fileName As String
For Each fi In fis
fileName = fi.Name
Select Case fileName.Substring(fileName.Length - 4).ToUpper
Case ".RDL"
PublishReport(sourceFolder, fileName, targetFolder)
Case ".JPG", ".JPEG"
PublishResource(sourceFolder, fileName, "image/jpeg", targetFolder)
Case ".GIF", ".PNG", ".BMP"
PublishResource(sourceFolder, fileName, "image/" + fileName.Substring(fileName.Length - 3).ToLower, targetFolder)
End Select
Next fi
End Sub
Public Sub PublishReport(ByVal sourceFolder As String, ByVal reportName As String, ByVal targetFolder As String)
Dim definition As [Byte]() = Nothing
Dim warnings As Warning() = Nothing
Try
Dim stream As FileStream = File.OpenRead(sourceFolder + "\" + reportName)
definition = New [Byte](stream.Length) {}
stream.Read(definition, 0, CInt(stream.Length))
stream.Close()
Catch e As IOException
Console.WriteLine(e.Message)
End Try
Try
'name, folder, overwrite, definition, properties
warnings = rs.CreateReport(reportName.Substring(0, reportName.Length - 4), targetFolder, True, definition, Nothing)
If Not (warnings Is Nothing) Then
Dim warning As Warning
For Each warning In warnings
Console.WriteLine(warning.Message)
Next warning
Else
Console.WriteLine("Report: {0} published successfully with no warnings", targetFolder + "/" + reportName)
End If
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
Public Sub PublishResource(ByVal sourceFolder As String, ByVal resourceName As String, ByVal resourceMIME As String, ByVal targetFolder As String)
Dim definition As [Byte]() = Nothing
Dim warnings As Warning() = Nothing
Try
Dim stream As FileStream = File.OpenRead(sourceFolder + "\" + resourceName)
definition = New [Byte](stream.Length) {}
stream.Read(definition, 0, CInt(stream.Length))
stream.Close()
Catch e As IOException
Console.WriteLine(e.Message)
End Try
Try
'name, folder, overwrite, definition, MIME, properties
rs.CreateResource(resourceName, targetFolder, True, definition, resourceMIME, Nothing)
Console.WriteLine("Resource: {0} with MIME {1} created successfully", targetFolder + "/" + resourceName, resourceMIME)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
Here is the batch to call the rs.exe:
SET ReportServer=%1
SET DBServer=%2
SET DBName=%3
SET ReportFolder=%4
rs -i PublishReports.rss -s %ReportServer% -v dbServer="%DBServer%" -v db="%DBName%" -v parentFolder="%ReportFolder%" >PublishReports.log 2>&1
pause
I used the script #David supplied but I had to add some code (I'm typing this up as an answer, as this would be too long for a comment.
The problem is: if there is already a "shared datasource" attached to a report in the report definition, this is never the same datasource as the one that is created in the script.
This also becomes apparent from the warning emitted by the "CreateReport" method:
The data set '' refers to the shared data source '', which is not published on the report server.
So the data source has to be set explicitly afterwards. I've made the following code changes:
I added a global variable:
Dim dataSourceRefs(0) As DataSource
At the end of the CreateDataSource method, that variable gets filled:
Dim dsr As New DataSourceReference
dsr.Reference = "/" + parentFolder + "/" + db
Dim ds As New DataSource
ds.Item = CType(dsr, DataSourceDefinitionOrReference)
ds.Name = db
dataSourceRefs(0) = ds
And in the PublishReport method, that data source gets explicitly set (after CreateReport has been called):
rs.SetItemDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
Note that this last call is only RS 2005 or higher. If you want to load your reports onto a RS 2000 server, you have to use SetReportDataSources in stead:
rs.SetReportDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
Well not really elegant. We created our own tool that uses the reportingservices2005 web service. We found this to be the most reliable way of getting what we want.
It's not really that difficult and lets you expand it to do other things like creating data sources and folders as required.
I strongly recommend RSScripter. As noted in the overview:
Reporting Services Scripter is a .NET
Windows Forms application that enables
scripting and transfer of all
Microsoft SQL Server Reporting
Services catalog items to aid in
transferring them from one server to
another. It can also be used to easily
move items on mass from one Reporting
Services folder to another on the same
server. Depending on the scripting
options chosen, Reporting Services
Scripter can also transfer all catalog
item properties such as Descriptions,
History options, Execution options
(including report specific and shared
schedules), Subscriptions (normal and
data driven) and server side report
parameters.
I know you say that you're not in favor of the Business Development Studio to do this, but I've found the built-in tools to be very reliable and easy to use.
Have you looked into any Continuous Integration solutions such as CruiseControl.NET? If you are able to deploy Reports using rs.exe then you can setup an automated process in CruiseControl to build and deploy your Reports on a timer or whenever a report is modified.
In our environment, we develop in VS with version control then deploy to DEV SSRS. Once the report is validated, we use ReportSync program to deploy reports from ReportServer DEV to ReportServer PROD. The RS.EXE scripts still have their place, but I have found ReportSync to be a much simpler and agile way to promote a report.
ReportSync:
ReportSync is an open source program free to download and use. It works great for downloading reports in bulk, and it can even push a report from one server to another server.
How to get download the program?
Download the source code files from Github: Phires/ReportSynch, Run VS, Open the solution file (.SLN), compile the program, find the executable file (.EXE) from the C:\Temp\reportsync-master\bin\Release folder. Finally, saved the .EXE somewhere for you to use regularly
How do I copy SSRS reports to a new server if I am not the owner of the reports --> ReportSync answer by nunespascal
How to deploy a report?
Run the executable and the interface will launch.
Use the SOURCE and DESTINATION dialogues to choose a single report, multiple reports, or an entire folder of reports. You can any target folder you would like. (HINT: You can even target the same server if you are wanting to duplicate a report on the same server.)
After making your selections press the Sync button
Go to the target server, and validate the change took effect by reviewing the Changed By Date.
This tool has been very convenient, but I have noticed some quirks. For example when I want to update just one report that already exists in the destination, here is what I have to select-- [Source:Report> Target:Folder> Sync]. WARNING: You might think you would select the target server report to update it, but I have tried this and the report does not get updated.
What else can ReportSync do?
There is also an Export feature, which works marvelously for simply dumping all the RDL files to a folder for me to access. This is helpful in the event you need to migrate the server, add the files to to a VS Solution Project, or do anything else will all the files.
In my testing this program does not migrate other content-- subscriptions, shared data sources, shared data sets. It is just applicable to the report files.
I know this post is old, but I came across it when researching RS.EXE scripts, so I thought I would provide an answer this question.