How to populate Crystal Reports with SQL - c#

Since there doesn't seem to be any way to load old VB6 (ActiveReports) reports in .Net, I need to recreate dozens of reports in .Net. I'd like to do this in the least painful way possible.
In VB6, the original authors simply did something like this for every report:
adoConn.ConnectionString = globalConnectionObject.ConnectionString
adoConn.Source = ReportFunctions.GetAllUsers()
GetAllUsers() returns an SQL string which selects a bunch of fields; those fields are then used in the report.
Now:
How can I do something similar in .Net (either using the built-in Crystal Reports, or the built-in "Microsoft Reporting Technology")?
I can't get "Database Expert" to recognize globalConnectionObject (an ADODB.Connection object); and if I fill a dataset and do
report.SetDataSource(dataSet)
It tells me "The report has no tables."
How do I populate a Crystal Reports report!? (the connection string/data location is not known at compile time)

Creating Connection:
/// <summary>
/// Sets the connection.
/// </summary>
public void SetConnection()
{
_connection = new SqlConnection(Settings.Default.connectionString);
if (_connection.State == System.Data.ConnectionState.Open)
{
_connection.Close();
}
_connection.Open();
}
/// <summary>
/// Closes the connection.
/// </summary>
public void CloseConnection()
{
if (_connection.State == System.Data.ConnectionState.Open)
{
_connection.Close();
_connection.Dispose();
}
}
using above connection Populate dataset manually or Add a dataset to your solution to get data without writing connection codes. Say You have added Employee.XSD. Add a tableadapter in the XSD which will help you in pulling data from database, by auto generating queries and datatables. After doing all these things. Create a method somewhere in your project,
Public DataTable GetAllEmployees()
{
Employee.EmployeeTableAdapter adapt = New Employee.EmployeeTableAdapter();
DataTable dt = New DataTable();
dt = adapt.GetData(); // you can also use fill based on your criteria.
return dt; //your datatable with data
}
Now on Your Form add a reportviewer control.
ReportViewer1 rpt = New ReportViewer();
ReportDocument rptDoc = new ReportDocument();
rptDoc.Load("path of rpt file");
rptDoc.SetDataSource(GetAllEmployees());
rpt.Document = rptDoc;
rpt.Refresh();
Before that From Crystal Report , add the fields of table on the report as per your requirement.
Another Way To achieve
Crystal Reports can be used over various objects. If you have scenario to bind it dynamically, see my answer below Then u can do one thing that is , add a new dataset to solution. Create a datatable and add required columns with appropriate data type. DO not add query or table adapter. Now from your code add a class file and create properties exactly similar to the datatable columns. Now set the datatable as source to report and add its column on the report.
For example , if you have columns
ID - integer
EmpName - string
Salary - double
Department - string
Create a class
public class Employee
{
private SqlConnection _connection;
public int ID {get;set;}
public string EmpName {get;set;}
public double Salary {get;set;}
public string Department {get;set;}
/// <summary>
/// Sets the connection.
/// </summary>
public void SetConnection()
{
//assuming connection string is placed in settings file from Project Properties.
_connection = new SqlConnection(Settings.Default.connectionString);
if (_connection.State == System.Data.ConnectionState.Open)
{
_connection.Close();
}
_connection.Open();
}
/// <summary>
/// Closes the connection.
/// </summary>
public void CloseConnection()
{
if (_connection.State == System.Data.ConnectionState.Open)
{
_connection.Close();
_connection.Dispose();
}
}
public DataTable GetEmployees()
{
DataTable dt = new DataTable("Employee");
// using above connection
SetConnection();
using(SqlCommand command = new SqlCOmmand("commandText",_connection))
{
using(SqlDataReader reader = command.ExecuteReader())
{
dt.Load(reader);
}
}
return dt;
}
}
Now create another function that will populate the datatable created inside the dtataset.
public void PopulateDataTable()
{
DataTable dt = GetEmployee();
Employee dsEmployee = New DataSet();
dsEmployee.EmployeeDataTable dtEmp = new dsEmployee.EmployeeDataTable();
dtEmp = dt;
}

We do something similar using Crystal Reports, and it has caused me to really dislike Crystal Reports. Using the database expert I created a new connection to the database and a new command with the SQL that I want to use. This defines the columns that Crystal Reports can use and allows you to create the report. Then when displaying the report we do:
ReportDocument rd = new ReportDocument();
rd.Load(MapPathSecure("NameOfMyReport.rpt"));
rd.SetDataSource(dataSet.Tables[0]);
I have only done it with one table, so I don't know how having multiple tables in the DataSet would affect it. Basically, you set the structure of the report with the Database Expert and the command. Then you overwrite the actual data at runtime. I really wish that Crystal Reports had a more robust way of doing this, or that I understood it if it exists.

Related

How Can I Show A Search Result In A Textbox?

I have created a table code and would like to search and retrieve an answer introducing device IMEI in TextBox IMEI und when I click on the search, I want to display the result code_mck in the textbox code i want display the result:
id Imei code_mck
1 356885021519453 830782136
2 356885021519156 948790617
3 356885021518893 715398945
4 356885021518935 567456626
5 359654022104377 557960750
Initially I have a typical three-layer architecture and the search method is in the Data Layer. I have some trouble with my SQL Query:
public DataSet recherche(string code)
{
DataSet ds = null;
using (OleDbConnection cnn = new OleDbConnection(strConn))
{
cnn.Open();
string Oledb = "SELECT * FROM Code WHERE Imei=#IMEI";
using (OleDbDataAdapter adapter = new OleDbDataAdapter(Oledb, cnn))
{
adapter.SelectCommand.Parameters.AddWithValue("#IMEI", code);
ds = new DataSet();
adapter.Fill(ds, "Code");
}
}
return ds;
}
Business Logic layer:
namespace unlock2_buisness
{
public class code_imei
public DataSet rechercheduCode(string imei)
{
unlockDAL objetDataLayer = new unlockDAL();
if (imei == "")
throw new Exception("merci d'indique l'imei de recherche");
DataSet dt = null;
dt = objetDataLayer.recherche(imei);
return dt;
}
In my User Layer, the TextBox dedicated for search to display the result in textbox code is not responding, and am not getting the appropriate code by providing the device IMEI as it should be from the table.
private void btnrechercheimei_Click(object sender, EventArgs e)
{
imeiLogic.rechercheduCode(txtimei.Text);
imeiLogic.rechercheduCode(txtcode.Text);
}
I will appreciate your support.
The problem is how you use your BusinesLogic class.
public DataSet rechercheduCode(string imei) takes a string as input parameter and returns a DataSet.
When you call the method like this:
imeiLogic.rechercheduCode(txtimei.Text);
you do provide the input parameter (the value that is in textbox) but you don't store the returned Dataset in a variable.
The dataset wil have a table called Code that will hold the result rows from the query or 0 rows if nothing is found.
Staying as close as possible to your current implementation I suggest this:
private void btnrechercheimei_Click(object sender, EventArgs e)
{
// call the BLL to get a dataset
var dataSet = imeiLogic.rechercheduCode(txtimei.Text);
// get our table in the dataset
var codeTable = dataSet.Tables["Code"]; // table
// check if there was a row returned
if (codeTable.Rows.Count > 0)
{
var row = codeTable.Rows[0]; // pick the first one
txtcode.Text = row["code_mck"].ToString(); // update our textbox
}
// Add handling for 0 rows and/or more than 1 rows returned
}

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();
}

Exceptions: System.NullReferenceException while trying to create relation between tables in dataSet

using C#, .net framework 4.5, VS 2012
Try to create simple relation between tables in data set, but got System.NullReferenceException, as I can see on MSDN, it's mean occurs when you try to reference an object in your code that does not exist. But, think i create all required objects.
My code below:
//create place for storing all tables from data base
private DataSet myDS = new DataSet("AutoLot");
//command builders for easy way access to tables
private SqlCommandBuilder sqlCInventory;
private SqlCommandBuilder sqlCOrders;
private SqlCommandBuilder sqlCCustomers;
//adapters for each table
private SqlDataAdapter sqlAInventory;
private SqlDataAdapter sqlAOrders;
private SqlDataAdapter sqlACustomers;
//connection string
private string cnStr = string.Empty;
public MainForm()
{
InitializeComponent();
//get connection string from .config file
cnStr =
ConfigurationManager.ConnectionStrings["AutoLotSqlProvider"].ConnectionString;
//create adapters
sqlACustomers = new SqlDataAdapter("Select * From Customers", cnStr);
sqlAInventory = new SqlDataAdapter("Select * From Inventory", cnStr);
sqlAOrders = new SqlDataAdapter("Select * From Orders", cnStr);
//automatic generate commands
sqlCCustomers = new SqlCommandBuilder(sqlACustomers);
sqlCInventory = new SqlCommandBuilder(sqlAInventory);
sqlCOrders = new SqlCommandBuilder(sqlAOrders);
//add table to data Set
sqlAInventory.Fill(myDS);
sqlAOrders.Fill(myDS);
sqlACustomers.Fill(myDS);
//create relationship between tables
BuildTableRelationShip();
//create DataSourse for datGrids on UI
dataGridViewCustomer.DataSource = myDS.Tables["Inventory"];
dataGridViewOrders.DataSource = myDS.Tables["Orders"];
dataGridViewCustomer.DataSource = myDS.Tables["Customers"];
}
and here I got exception
private void BuildTableRelationShip()
{
//create object of relationShips
DataRelation dr = new DataRelation("CustomersOrders", //name of relation
myDS.Tables["Customers"].Columns["CustID"], //main columns
myDS.Tables["Orders"].Columns["OrderID"]); //related columns
myDS.Relations.Add(dr);
//second relation
dr = new DataRelation("InventoryOrder",
myDS.Tables["Inventory"].Columns["CarID"],
myDS.Tables["Orders"].Columns["OrderID"]);
//add relations to dataset
myDS.Relations.Add(dr);
}
Why i got this Null reference Exception? What i miss?
EDIT
You should call fill on individual DataTables rather than the whole DataSet.
sqlAInventory.Fill(myDS);
sqlAOrders.Fill(myDS);
sqlACustomers.Fill(myDS);
would become
sqlAInventory.Fill(myDS, "Inventory");
sqlAOrders.Fill(myDS, "Orders");
sqlACustomers.Fill(myDS, "Customers");
This method will automatically add a table to your DataSet if it doesn't exist, and populates it with data if it does. MSDN has more information on this method of the fill.

Sqldataapter advice

At present i have a the following code populating a datagridview showing the user account information on our system. What i want to do do is have a checkbox on the datagridview for the option "accountenabled" and a update button at the bottom of the form so it will update all users that have had changes made against them. I am currently pulling the data back using an sqldatareader however from what i have read i need to use a sqldataadapter. I`ve created the column names on the datagridview and the reader is currently pulling everything back correctly.
Could someone please point me in the right direction of doing this with an sqldatadapter?
Thanks
public UserAdmin()
{
InitializeComponent();
//Load user list
// Locals
Functionality func = new Functionality();
SqlConnection supportDB = null;
SqlCommand CheckUser = null;
SqlDataReader rdr;
DataSet ds = new DataSet();
DataTable dt = new DataTable();
string User = System.Environment.UserName.ToString();
string spName = "gssp_ShowAllUsers";
try
{
using (supportDB = new SqlConnection(GSCoreFunc.ConnectionDetails.getConnectionString(ConnectionType.SupportDB)))
{
using (CheckUser = new SqlCommand(spName, supportDB))
{
// Set the command type
CheckUser.CommandType = CommandType.StoredProcedure;
// Populate the parameters.
CheckUser.Parameters.Add(func.CreateParameter("#spErrorID", SqlDbType.Int, ParameterDirection.Output, DBNull.Value));
// Open the connection and populate the reader with the SP output
supportDB.Open();
rdr = CheckUser.ExecuteReader();
if (CheckUser.Parameters["#spErrorID"].Value != null)
{
throw new InvalidOperationException();
}
// If the data reader has rows display output on label
if (rdr.HasRows)
{
//Output values
while (rdr.Read())
{
//Bind to data table
dgvUsers.Rows.Add(rdr["agentID"].ToString(), rdr["createdon"].ToString(), rdr["firstname"].ToString(), rdr["lastname"].ToString(), rdr["username"].ToString(), rdr["emailaddress"].ToString(), rdr["Departments"].ToString(), rdr["accountenabled"].ToString(), rdr["AgentAccountLevel"].ToString());
}
}
// Close reader and connection.
rdr.Close();
supportDB.Close();
}
}
}
catch (Exception ex)
{
//Show error message
string error = ex.ToString(); //Real error
string FriendlyError = "There has been error loading the user list"; // Error user will see
GSCoreFunc.ShowMessageBox.msgBoxErrorShow(FriendlyError);
//Log error to ExceptionDB
GSCoreFunc.ReportException.reportEx(GSCoreFunc.ApplicationInformation.ApplicationName, error, FriendlyError, GSCoreFunc.ApplicationInformation.ComputerName, GSCoreFunc.ApplicationInformation.OperatingSystem, GSCoreFunc.ApplicationInformation.screenSize, GSCoreFunc.ApplicationInformation.IPAdddress, GSCoreFunc.ApplicationInformation.domainName);// Pass error to GSCoreFunc to log to the ExceptionDB
}
}
private void btClose_Click(object sender, EventArgs e)
{
//Close window
Close();
}
}
}
There is nothing wrong with using the SqlDataReader. The SqlDataAdapter is a higher level api that allows you to iterate through an SqlDataReader and store a copy of the results in a DataTable or a DataSet. This copy can then be used as the data source for your DataGridView.
One thing I would change with your code would be to use data binding instead of generating each row manually. If you set the DataSource property of the grid to either your SqlDataReader or to a DataTable filled by an SqlDataAdapter and then call the grids DataBind() method the grid should be filled automatically with your data.
To control the columns you would make sure your query only returns the required columns, and you would define the column setup in your aspx-file.
Using data binding is generally an easier and more flexible approach, so you should consider using that instead.
Look at this code
Initialize a sql adapter and fill with data source . Use a connection string other than using sql data source because it would be easy for customizing. :)

Datatable insertion in SQL using c#

How can we insert the values of datatable in SQL using c#? And the second question is how we can copy the SQL table into datatable variable?
UPDATE: One thing this answer didn't have in the past is links to information for SQL and database newbies, so I will put some relevant links here as well so that you (or anyone else) can brush up on their SQL and other database design skills.
W3 Schools SQL Tutorial
Database Design Tutorial
UPDATE 2: Here is an example of filling a datatable:
//Namespace References
using System.Data;
using System.Data.SqlClient
/// <summary>
/// Returns a DataTable, based on the command passed
/// </summary>
/// <param name="cmd">
/// the SqlCommand object we wish to execute
/// </param>
/// <returns>
/// a DataTable populated with the data
/// specified in the SqlCommand object
/// </returns>
/// <remarks></remarks>
public static DataTable GetDataTable(SqlCommand cmd)
{
try
{
// create a new data adapter based on the specified query.
SqlDataAdapter da = new SqlDataAdapter();
//set the SelectCommand of the adapter
da.SelectCommand = cmd;
// create a new DataTable
DataTable dtGet = new DataTable();
//fill the DataTable
da.Fill(dtGet);
//return the DataTable
return dtGet;
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
A lot of this is taken from another answer I have written previously, but it goes into detail about your exact issues:
Original Answer:
This sounds like you more or less need a basic introduction to connecting and manipulating a database from C#. The above poster said to look into LINQ to SQL, but you can also look into the more basic underlying framework of ADO.NET which will get you to understand the basics of how it works.
Also, you can use this site right here for a number of different database tutorials for C#.
Edit: More information from C# Station, CodeProject, and Codersource
Edit 2: If you are interested in things like Linq to SQL as others have mentioned above, here are some tutorials from C# Corner, and C-Sharp Online
Edit 3: Others would also suggest things such as the ADO.NET Entity Framework. I would not necessarily suggest this for beginners who still need to grasp the fundamentals of working with a database. Here is some information from the MSDN Overview
Simple Example (This is pulled directly from the C# Station link given above)
Listing 1. Using a SqlConnection
using System;
using System.Data;
using System.Data.SqlClient;
/// <summary>
/// Demonstrates how to work with SqlConnection objects
/// </summary>
class SqlConnectionDemo
{
static void Main()
{
// 1. Instantiate the connection
SqlConnection conn = new SqlConnection(
"Data Source=(local);Initial Catalog=Northwind;
Integrated Security=SSPI");
SqlDataReader rdr = null;
try
{
// 2. Open the connection
conn.Open();
// 3. Pass the connection to a command object
SqlCommand cmd =
new SqlCommand("select * from Customers", conn);
//
// 4. Use the connection
//
// get query results
rdr = cmd.ExecuteReader();
// print the CustomerID of each record
while (rdr.Read())
{
Console.WriteLine(rdr[0]);
}
}
finally
{
// close the reader
if (rdr != null)
{
rdr.Close();
}
// 5. Close the connection
if (conn != null)
{
conn.Close();
}
}
}
}
For both of these, you want a relevant data adapter, e.g. SqlDataAdapter.
I suggest you find a good ADO.NET book or tutorial - it's bound to be in there. Alternatively, there are MSDN articles on DataAdapters/DataReaders and Retrieving and Modifying Data in ADO.NET.
I would read up on ADO.NET and LINQ to SQL for starters.

Categories