PrintToPrinter method for crystal reports throws logon exception - c#

I am using PrintToPrinter(1,false,1,1) in my website for a crystal report . After I click on this button ( btnPrintToPrinter) it throws LogOnException and says Database Logon failed :
protected void btnPrintToPrinter_Click(object sender, EventArgs e)
{
int empno = Convert.ToInt32(Session["AnyVal"]);
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
string strQuery = "SELECT [View_EmplDetail].[Uni-Code], [View_EmplDetail].[FacultyCode], [View_EmplDetail].[EmpIDstr], [View_EmplDetail].[EngGivenName], [View_EmplDetail].[position_eng], [View_EmplDetail].[Emp_no], [View_EmplDetail].[GivenName], [View_EmplDetail].[position_name], [View_EmplDetail].[DariName], [Tbl_Dept].[EName], [View_EmplDetail].[photo] FROM [MoHEDatabase].[dbo].[View_EmplDetail] [View_EmplDetail] INNER JOIN [MoHEDatabase].[dbo].[Tbl_Dept] [Tbl_Dept] ON [View_EmplDetail].[DepCode]=[Tbl_Dept].[DepCode] WHERE [Emp_no] = #empno";
SqlCommand command = new SqlCommand(strQuery, connection);
command.CommandType = System.Data.CommandType.Text;
command.Parameters.AddWithValue("#empno", empno);
command.Connection = connection;
command.Connection.Open();
SqlDataAdapter da = new SqlDataAdapter(command);
DataTable dt = new DataTable();
da.Fill(dt);
ReportDocument rpt = new ReportDocument();
string _reportPath = Server.MapPath("..\\Student\\cardFinal.rpt");
//rpt.Load(AppDomain.CurrentDomain.BaseDirectory + "\\" + #"\\Student\\CardFinal.rpt");
rpt.Load(_reportPath);
rpt.SetDataSource(dt);
emp_card_report_viewer.ReportSource = rpt;
string sq = "";
//{View_OrgStr1.Uni-Code}=0 and {View_OrgStr1.FacultyCode}=119
//sq = "{View_StudentAddNew.Student_ID}=" + Session["AnyVal"];
if (Session["AnyVal"].ToString() != "")
{
sq = "{View_EmplDetail.Emp_no}=" + int.Parse(Session["AnyVal"].ToString());
}
//emp_card_report.Report.FileName = "../Student/CardFinal.rpt";
emp_card_report_viewer.SelectionFormula = sq;
//ConnectionInfo connInfo = new ConnectionInfo();
//connInfo.ServerName = "172.16.0.15";
//connInfo.DatabaseName = "MoHEMISDatabase";
//connInfo.UserID = "myuser";
//connInfo.Password = "myuser#sabir";
//TableLogOnInfos crtt = new TableLogOnInfos();
//TableLogOnInfo crtto = new TableLogOnInfo();
//Tables crtables;
//crtables = rpt.Database.Tables;
//foreach (CrystalDecisions.CrystalReports.Engine.Table crtable in crtables)
//{
// crtto = crtable.LogOnInfo;
// crtto.ConnectionInfo = connInfo;
// //crtable.ApplyLogInInfo(crtto);
//}
ConnectionInfo connInfo1 = new ConnectionInfo();
// connInfo1.ServerName = "server";
setDBLOGONforReport(connInfo1);
//emp_card_report_viewer.RefreshReport();
//ConnectionInfo connInfo = new ConnectionInfo();
//connInfo.ServerName = "server";
//connInfo.DatabaseName = "MoHEDatabase";
//connInfo.UserID = "hemis_admin";
//connInfo.Password = "hemis#sabir";
//setDBLOGONforReport(connInfo);
CrystalDecisions.Shared.PageMargins pageMargins = new
CrystalDecisions.Shared.PageMargins(0, 0, 0, 0);
rpt.PrintOptions.ApplyPageMargins(pageMargins);
rpt.PrintOptions.PrinterName = printerList.SelectedItem.Value;
emp_card_report_viewer.RefreshReport();
rpt.PrintToPrinter(1, false, 1, 1);
rpt.Close();
rpt = null;
}
error appears at : rpt.PrintToPrinter(1,falase,1,1);
any idea where it goes wrong ???
I have commented out some of the lines, just was checking on them ...
any help would be appreciated...tnx

Lucky, I suspect you don't mean "after I compile" that it throws the error. I'm assuming you mean "after I click my 'btnPrintToPrinter' button in my web application"? Whatever the case, please update the question to be more specific in how you trigger the error?
If your 'btnPrintToPrinter' button is sitting on the web page the moment you click it you get database logon failed, it is probably because you are doing two things that contradict each other:
1) You first assign a database as the report's datasource.
-THEN-
2) You are setting connection details for the report, i.e.
ConnectionInfo connInfo1 = new ConnectionInfo();
setDBLOGONforReport(connInfo1);
Remove these extra steps where you set connection info. The report doesn't need connection information if you are PUSHING a datatable to it. (Once you feed a report data it isn't going to connect to the server to get the data again.)
Note: IF you still see problems after you remove these lines. The issue is probably that the datatable you are passing is not what the report was build on in the first place. For example:
1) You built the report using a table named 'TableA' with 'field1', 'field2' and 'field3'.
2) Then you build a datatable in your code by querying 'TableA' with 'field1', 'field2' and 'fieldx' and 'fieldz'.
3) You pass the table from #2 into the report.
This can cause database logon errors (even though it's not really a logon problem). Because the report does this:
1) It TRIES to use the data you passed in. Then it CAN'T because the fields do not match what the report was designed from.
2) THEN the report, having no data, attempts to connect to the database server it WAS built on before.
3) Since you haven't (and should not) pass valid connection information to the report, it NOW throws 'database logon failed'.
So you see, it isn't really because the logon failed that you have a problem. It's because the data you provided (which makes the report NOT NEED to connect) was invalid data. As I said earlier, even one field being different can make the report fail. In fact, even just changing a single field's type (say varchar to int, or varchar(5) to nvarchar(10), etc.) can make the data you pass NOT match the data the report was built on.
So in your page load event (where I'm assuming you set

I have used this:
myReport.SetDatabaseLogon("username","password");
method and it solved the problem.

Related

How can I redirect to Report Viewer?

I am facing a problem while working with Reports in WPF... I have created an event
private void Window_Loaded(object sender, RoutedEventArgs e) {
try {
admissionReportViewer.Owner = Window.GetWindow(this);
if (_admissionNumber != 0) {
rd.Load(#"C:\\Users\Sohaib Khalid\source\repos\SMS Degree College\Reports\AdmissionForm - Copy.rpt");
SqlConnection conn = new SqlConnection();
conn.ConnectionString = ConfigurationManager.ConnectionStrings["Other"].ConnectionString;
conn.Open();
SqlDataAdapter sda = new SqlDataAdapter("SearchStudentInfoAllById", conn);
sda.SelectCommand.CommandType = System.Data.CommandType.StoredProcedure;
sda.SelectCommand.Parameters.AddWithValue("#AdmissionNumber", _admissionNumber);
sda.SelectCommand.Parameters.AddWithValue("#Active", _active);
DataSet ds = new DataSet();
sda.Fill(ds, "StudentTable");
rd.SetDataSource(ds);
admissionReportViewer.ViewerCore.ReportSource = rd;
}
}
catch(Exception err) {
this.ShowMessageAsync("No data", err.ToString());
Debug.WriteLine(err.ToString());
}
after this report also load but it again, ask for parameters:
and also credentials of server login
Can Anybody tell me why it is again asking for parameters?
Thanks
I never used ReportViewer in WPF app, but used it a couple of time on ASP.NET
If WPF works in the same way, you're code is wrong:
The report is using the data source you set up for design it and not the one you're passing to it
You're storing the parameter value in the data adapter (query) and not in the report parameters
This is why your report ask for both.
I'll share a bit of code for ASP, try to check if it can be the same for WPF or if you have to change it:
// Local mode says to use the datasource we are giving to the report
// instead of the one we used to design it
reportViewer.ProcessingMode = ProcessingMode.Local;
// Set the path of the report file
LocalReport localReport = reportViewer.LocalReport;
localReport.ReportPath = "PATH_OF_YOUR_REPORT";
// Extract data from the DB (remember to insert the parameters in the query)
var dataset = GetDataSet();
// Assign the dataset to the report source (we need a ReportDataSource)
var source = new ReportDataSource();
source.Name = "SOURCE_NAME_USED_IN_THE_REPORT";
source.Value = dataset.Tables["YOUR_TABLE"];
// Add the source to the report
localReport.DataSources.Add(source);
// Create your report parameter (ex: fromDate)
var paramFromDate = new ReportParameter();
paramDataDa.Name = "fromDate";
paramDataDa.Values.Add(paramFromDate.ToShortDateString());
// Set the report parameters for the report
localReport.SetParameters(new ReportParameter[] { fromDate });
I hope this can help you but remember, it is for ASP and not for WPF.
So try to adapt it to WPF and see if they work in the same way

A data source instance has not been supplied for the data source 'DataSet2'-SSRS

This is my First report using SSRS.
I am trying to generate a Report using SSRS in asp.net.
My Need is:
I want to create a report with multiple tables (4 tables) that have relationship with one another. I have configured each individual table with accepting 1 parameter, for instance:
What I tried is:
I have created a dataset.xsd with 4 tables and given the relationship between those tables.
Then I created a report.rdlc and designed a report with four tables and drag and dropped the required field to the table and created a report parameter called ID.
The error i'm Getting is:
A data source instance has not been supplied for the data source 'DataSet2'
What I have written in cs page on button click is:
protected void BtnGo_Click(object sender, EventArgs e)
{
DataSet2TableAdapters.TB_TransReceiptTableAdapter ta = new DataSet2TableAdapters.TB_TransReceiptTableAdapter();
DataSet2.TB_TransReceiptDataTable dt = new DataSet2.TB_TransReceiptDataTable();
ta.Fill(dt,Convert.ToInt16( TxtID.Text));
//ta.Fill(dt,TxtID.Text);
ReportDataSource rds = new ReportDataSource();
rds.Name = "DataSet2";
rds.Value = dt;
ReportParameter rp = new ReportParameter("ID", TxtID.Text.ToString());
rptviewer.LocalReport.DataSources.Clear();
rptviewer.LocalReport.ReportPath = "Report1.rdlc";
rptviewer.LocalReport.SetParameters(new ReportParameter[] { rp });
rptviewer.LocalReport.DataSources.Add(rds);
rptviewer.LocalReport.Refresh();
rptviewer.Visible = true;
}
The help i seek is:
I dont know how to bind the report via code, since I have four tables that are related to one another with foreign key. Above is the code I used but it throws an error.
I would be very thankful if some one could help me to solve this issue.
Thanks in advance.
As per tgolisch instead of table i Bound dataset and passed to report it works fine.
And also instead of four separate table i created a view .It Makes my job simple
private DataTable getData()
{
DataSet dss = new DataSet();
string sql = "";
sql = "SELECT * from VW_TransReciptReport WHERE tREC_NUPKId='" + TxtID.Text + "'";
SqlDataAdapter da = new SqlDataAdapter(sql, con);
da.Fill(dss);
DataTable dt = dss.Tables[0];
return dt;
}
private void runRptViewer()
{
this.rptviewer.Reset();
ReportParameter rp = new ReportParameter("ID", TxtID.Text.ToString());
this.rptviewer.LocalReport.ReportPath = Server.MapPath("ReportReceipt.rdlc");
rptviewer.LocalReport.SetParameters(new ReportParameter[] { rp });
ReportDataSource rdsB = new ReportDataSource("DataSet1_VW_TransReciptReport", getData());
this.rptviewer.LocalReport.DataSources.Clear();
this.rptviewer.LocalReport.DataSources.Add(rdsB);
this.rptviewer.DataBind();
this.rptviewer.LocalReport.Refresh();
}

C# Login Screen - Find User in SQL Table and Update Field

I am currently writing a small application to keep track of monetary ins and outs, something just to improve my general C# skills. For my Login Screen currently I have the following Code
private void Login_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'spendingInsAndOutsDataSet.Users' table. You can move, or remove it, as needed.
this.usersTableAdapter.Fill(this.spendingInsAndOutsDataSet.Users);
}
private void button1_Click(object sender, EventArgs e)
{
string userNameText = userName.Text;
string passwordText = password.Text;
foreach (DataRow row in spendingInsAndOutsDataSet.Users)
{
if (row.ItemArray[4].Equals(userNameText) && row.ItemArray[5].Equals(passwordText))
{
MessageBox.Show("Login Successful");
MainGUI newForm = new MainGUI();
this.Visible = false;
newForm.Show();
break;
}
else
{
userName.Text = String.Empty;
password.Text = String.Empty;
MessageBox.Show("Login Failed");
break;
}
}
}
What I am looking to do when the Login is Sucessful is to write the MachineName of the current PC to a field in Users table in my SQL Database. That way when I come to start creating records I can quickly find my UsersId (which is a foreign key in my Transactions table).
I know you can get the Active Machine Name using the System.Enviroments path but Im unsure exactly how to go about writing the update. I know how to do it using a SqlCommand but I am wondering if there is a simpler way using the DataRows I have used within the ForEach loop.
Thanks in advance, any questions let me know.
James
Assuming it is an Access database (If not then make the necessary changes):
Use an Adapter to fill a table with your results. Then compare the row columns with the information provided by the user. Don't forget to use parameters to avoid injections that may potentially ruin your database or expose your user's information to a hacker.
DataTable dt = new DataTable();
String sql = "SELECT * FROM users WHERE user = #user and password=#password"
OleDbConnection connection = getAccessConnection();
OleDbDataAdapter da = new OleDbDataAdapter(sql, connection);
da.SelectCommand.Parameters.Add("#user", OleDbType.VarChar).Value = userNameText;
da.SelectCommand.Parameters.Add("#password", OleDbType.VarChar).Value = password.Text;
try
{
connection.Open();
da.Fill(dt);
connection.Close();
}
catch(OleDbException ex)
{
connection.Close();
MessageBox.Show(ex.ToString());
}
if(dt.Rows.Count == 1)
return true; //username && password matches
else if(dt.Rows.Count == 0)
return false; // does not match
You could also use AddWithValue for your parameters.
da.SelectCommand.Parameters.AddWithValue("#user", userNameText);
getAccessConnection() is a predefined OleDbConnection function that has the connection to the database setup and creates a new instance of the connection for you (that I have created for myself).
public OleDbConnection getAccessConnection()
{
this.connection = new OleDbConnection();
this.connection.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source="
+ Classified.SOURCE + ";Jet OLEDB:Database Password="
+ Classified.PASS + ";";
return this.connection;
}
It is preferred to create classes for all of these functions for developers who may join in on the project. Also read up on C# test driven development as well.
Also it looks like your loop will break even if that one record fails, only allowing it to go to it's first record.
Onto creating your own data set and filling it with queried tables is also useful. Here is a brief example:
DataSet ds = new DataSet();
ds.Tables.Add(dt, "userSearchedTable");
ds.Tables["userSearchedTable"].Rows[0][1].ToString();
Then you can declare a specific data table within the set when ever you need to.
In your foreach loop, set the MachineName of the current PC on relevant row then at the end of the method call:
this.usersTableAdapter.Update(this.spendingInsAndOutsDataSet.Users);
This will update the database with the machine name
However looking at your code there are a few additional comments to make I'd like to add to improve what you have:
You are loading the entire data table and then checking it for the username and password. Really you query for the user ID in the database, load that single row and check the password. If you have many users, your current implementation will create a lot of network traffic.
Instead of:
foreach (DataRow row in spendingInsAndOutsDataSet.Users)
Consider using something like:
foreach (SpendingInsAndOutsDataSet.UsersRow row in spendingInsAndOutsDataSet.Users)
i.e. the strongly typed version of the data row object. This means you can use:
row.Username.Equals(userNameText)
instead of
row.ItemArray[4].Equals(userNameText)
Also if you are anticipating that this will be used over a network, you should look to encrypt the passwords.

how to reference to a fileupload control in a dataset

In my program, when user wants to edit a record, and presses Edit button, a new window opens up with all the fields and record information is rendered into the respective fields giving user an option to edit any field information they require.
I have added a fileupload control to my webform fields. But I am not sure how to reference fileupload control on my new popped up window .. I am not sure if I am explaining my problem very clearly or not but I will try to explain it with the help of following code:
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
lblSet.Text = GridView1.Rows[e.NewEditIndex].Cells[2].Text;
MultiView1.SetActiveView(vRecord);
btnSave.Visible = false;
btnBacktoHome.Visible = true;
//this.lblMedium.Text = GridView1.Rows[e.NewEditIndex].Cells[1].Text;
using (SqlConnection con = new SqlConnection("Data Source=MEHDI-PC\\SQLEXPRESS;Initial Catalog=PIMS;Integrated Security=True"))
{
using (SqlCommand cmd = new SqlCommand())
{
String sql = "select [DocumentID],[Ref],[Subject],[Src],[Dst],[Medium],[Date_Printed],[Date_Received],[Document_Type],[Action_Required],[Due_Date],[Actual_Date],[Content],[Tag],[Issue_No],[Attachment],[Notes],[Assigned_To],[Reply_Ref],[Priority],[Status],[Response],[Physical_File_No],[Physical_Rack_Location] from dbo.Documents1 where [DocumentId]=N'" + GridView1.Rows[e.NewEditIndex].Cells[2].Text + "'";
cmd.Connection = con;
cmd.CommandText = sql;
con.Open();
//SqlDataAdapter da = new SqlDataAdapter(sql,con);
//DataTable dt = new DataTable();
DataSet ds = new DataSet();
using (SqlDataAdapter adp = new SqlDataAdapter(cmd))
{
adp.Fill(ds);
}
this.txtRef.Text = ds.Tables[0].Rows[0][1].ToString();
this.txtSubject.Text = ds.Tables[0].Rows[0][2].ToString();
this.ddlSource.Text = ds.Tables[0].Rows[0][3].ToString();
this.ddlDestination.Text = ds.Tables[0].Rows[0][4].ToString();
this.ddlMedium.Text = ds.Tables[0].Rows[0][5].ToString();
this.txtDatePrinted.Text = ds.Tables[0].Rows[0][6].ToString();
this.txtDateReceived.Text = ds.Tables[0].Rows[0][7].ToString();
this.ddlDocumentType.Text = ds.Tables[0].Rows[0][8].ToString();
this.cbxAction.Checked = ds.Tables[0].Rows[0][9].Equals(cbxAction.Checked);
this.txtDueDate.Text = ds.Tables[0].Rows[0][10].ToString();
this.txtActualDate.Text = ds.Tables[0].Rows[0][11].ToString();
this.txtContent.Text = ds.Tables[0].Rows[0][12].ToString();
this.txtTag.Text = ds.Tables[0].Rows[0][13].ToString();
this.txtIssue.Text = ds.Tables[0].Rows[0][14].ToString();
//this.fileupload1 = ds.Tables[0].Rows[0][15] ;
this.txtNotes.Text = ds.Tables[0].Rows[0][16].ToString();
this.ddlAssignedTo.Text = ds.Tables[0].Rows[0][17].ToString();
this.txtReplyRef.Text = ds.Tables[0].Rows[0][18].ToString();
this.ddlPriority.Text = ds.Tables[0].Rows[0][19].ToString();
this.ddlStatus.Text = ds.Tables[0].Rows[0][20].ToString();
this.ddlResponse.Text = ds.Tables[0].Rows[0][21].ToString();
this.txtPhysicalFileNo.Text = ds.Tables[0].Rows[0][22].ToString();
this.txtPhysicalRackLocation.Text = ds.Tables[0].Rows[0][23].ToString();
if (con != null)
{
con.Close();
}
btnUpdate.Visible = true;
btnSearch.Visible = false;
BindGrid();
}
}
}
Basically when user clicks edit, what my code does is, reads the relevant record in the sql server and loads it from there to a new popped up window in my webform .. puts all the information in the related fields.
I read online that reading varbinary data from sql and binding it into the webform is not as simple as calling text data. (maybe I am wrong, please correct me if i am). I am not really worried about fetching data from sql server into the webform, I am worried about referring to the upload control in the new window because if user add a new file in fileupload control in the popped up window and if its not referenced in my code, my program ignores the new uploaded file which is a big flaw in my code.
Problem is with this line of code:
//this.fileupload1 = ds.Tables[0].Rows[0][15] ;
I have commented it out for other code to run.
I am stuck with it for a whole week. Any help will be so much appreciated. Thanks in advance.
You can't bind a record to a file upload control, this control is for uploading files
not
downloading.
Have a look at this link for how to download files.
The upload control should be used to replace the existing file,when the user chooses to replace it i.e. the user will upload a new file and in your business logic you need to update this record using the existing record ID.
In your case I'd bind the ID of the attachment to a hidden field in the grid and leave the upload control alone. When the record is updated check if the file upload control has a file and then using the value of the attachment update the attachment.
Edit: From here I believe you would need to add something along the lines of:
FileUpload file = ((FileUpload)(GridView1.Rows[e.NewEditIndex].FindControl("myFileUploadControl")));
You need to give your file upload control an ID of myFileUploadControl (or whatever you want)
This question also discusses using a fileupload control in a gridview.

i would like to get the following information of a database please suggests ways [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
My need is to write a code, which
creates a db
creates four tables
creates primary keys
creates foreign keys
and constraints like type int or boolean or string etc
Yes I know w3c shools has the sql codes, but the problem is I first need to detect if these things exists or not one by one.
And this is for me a great problem.
I tried to work with sql exceptions, but it does not provide way to categorize the exceptions --like databasethereexception--tablealreadythereEXCEPTION..
So please provide some coded examples or links for the above purpose,
note: yes I can google, but it is full full full of examples and codes, it gets too confusing, so hoping for straight professional examples please
Also a sample of the type of code i am working with
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Data;
public partial class Making_DB : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//check or make the db
MakeDB();
CheckDB();
}
public void CheckDB()
{
try
{
string Data_source = #"Data Source=A-63A9D4D7E7834\SECOND;";
string Initial_Catalog = #"Initial Catalog=master;";
string User = #"User ID=sa;";
string Password = #"Password=two";
string full_con = Data_source + Initial_Catalog + User + Password;
SqlConnection connection = new SqlConnection(full_con);
connection.Open();
SqlDataAdapter DBcreatingAdaptor = new SqlDataAdapter();
DataSet ds2 = new DataSet();
SqlCommand CheckDB = new SqlCommand("select * from sys.databases where name = 'my_db'", connection);
DBcreatingAdaptor.SelectCommand = CheckDB;
DBcreatingAdaptor.Fill(ds2);
GridView1.DataSource = ds2;
GridView1.DataBind(); // do not forget this//
Response.Write("<br />WORKING(shows zero if db not there) checking by gridview rows: " + GridView1.Rows.Count.ToString());
Response.Write("<br />NOT WORKING(keeps on showing one always!) checking by dataset tables: " + ds2.Tables.Count.ToString());
DBcreatingAdaptor.Dispose();
connection.Close();
//Inaccesible due to protection level. Why??
//SqlDataReader reader = new SqlDataReader(CheckDB, CommandBehavior.Default);
}//try
catch (Exception e)
{
Response.Write(" checking:: " + e.Message);
}//catch
}//check db
public void MakeDB()
{
try
{
string Data_source = #"Data Source=A-63A9D4D7E7834\SECOND;";
//string Initial_Catalog = #"Initial Catalog=replicate;";
string User = #"User ID=sa;";
string Password = #"Password=two";
string full_con = Data_source + User + Password;
SqlConnection connection = new SqlConnection(full_con);
connection.Open();
//SqlCommand numberofrecords = new SqlCommand("SELECT COUNT(*) FROM dbo.Table_1", connection);
SqlCommand CreateDB = new SqlCommand("CREATE DATABASE my_db", connection);
//DataSet ds2 = new DataSet();
SqlDataAdapter DBcreatingAdaptor = new SqlDataAdapter();
DBcreatingAdaptor.SelectCommand = CreateDB;
DBcreatingAdaptor.SelectCommand.ExecuteNonQuery();
//check for existance
//select * from sys.databases where name = 'my_db'
DataSet ds2 = new DataSet();
SqlCommand CheckDB = new SqlCommand(" select * from sys.databases where name = 'my_db'", connection);
DBcreatingAdaptor.SelectCommand = CheckDB;
//DBcreatingAdaptor.SelectCommand.ExecuteReader();
DBcreatingAdaptor.Fill(ds2);
GridView1.DataSource = ds2;
//if not make it
}//try
catch (Exception e)
{
Response.Write("<br /> createing db error: " + e.Message);
}//catch
}//make db
}
As I've already mentioned in my comment - I would NEVER write out directly to the Response stream from a function like this! Pass back a string with an error message or something - but do NOT write out to the stream or screen directly.
You should use the best practice of wrapping SqlConnection and SqlCommand into using(...){.....} blocks to make sure they get properly disposed. Also, populating a gridview from within this code is really bad - you're mixing database access (backend) code and UI frontend code - really really bad choice. Why can't you just pass back the data table and then bind it in the UI front end code to the grid??
public DataTable CheckDB()
{
DataTable result = new DataTable();
try
{
string connectionString =
string.Format("server={0};database={1};user id={2};pwd={3}"
"A-63A9D4D7E7834\SECOND", "master", "sa", "two");
string checkQuery = "SELECT * FROM sys.databases WHERE name = 'my_db'";
using(SqlConnection _con = new SqlConnection(connectionString))
using(SqlCommand _cmd = new SqlCommand(checkQuery, _con))
{
SqlDataAdapter DBcreatingAdaptor = new SqlDataAdapter(_cmd);
DBcreatingAdaptor.Fill(_result);
}
}//try
catch (SqlException e)
{
// you can inspect the SqlException.Errors collection and
// get **VERY** detailed description of what went wrong,
// including explicit SQL Server error codes which are
// unique to each error
}//catch
return result;
}//check db
Also - you're doing the MakeDB() method way too complicated - why a table adapter?? All you need is a SqlCommand to execute your SQL command - you already have a method that checks that a database exists.
public void MakeDB()
{
try
{
string connectionString =
string.Format("server={0};database={1};user id={2};pwd={3}"
"A-63A9D4D7E7834\SECOND", "master", "sa", "two");
string createDBQuery = "CREATE DATABASE my_db";
using(SqlConnection _con = new SqlConnection(connectionString))
using(SqlCommand _cmd = new SqlCommand(createDBQuery, _con))
{
_con.Open();
_cmd.ExecuteNonQuery();
_con.Close();
}
}//try
catch (SqlException e)
{
// check the detailed errors
// error.Number = 1801 : "database already exists" (choose another name)
// error.Number = 102: invalid syntax (probably invalid db name)
foreach (SqlError error in e.Errors)
{
string msg = string.Format("{0}/{1}: {2}", error.Number, error.Class, error.Message);
}
}//catch
}//make db
I am very sure of the cross-over between this and the other question - however, it sounds to me like you are approaching this from the wrong end.
I would write this as a TSQL script, making use of EXEC to avoid problems with the checker, for example:
USE [master]
if not exists ( ... database ...)
begin
print 'creating database...'
exec ('...create database...')
end
GO
USE [database]
if not exists( ... check schema tables for 1st thing ... )
begin
print 'Creating 1st thing...'
exec ('...create 1st thing...')
end
if not exists( ... check schema tables for 2nd thing ... )
begin
print 'Creating 2nd thing...'
exec ('...create 2nd thing...')
end
if not exists( ... check schema tables for 3rd thing ... )
begin
print 'Creating 3rd thing...'
exec ('...create 3rd thing...')
end
Then you can gradually extend this script as your schema changes, and all you need to do is re-run the script for it to update the database.
May be it is not directly you want, but for easy database creation & population from .Net review usage of wide migrate tool. My preference (Migrator.NET) but full review can be found there: http://flux88.com/blog/net-database-migration-tool-roundup/

Categories