Calling the functionfrom one class to another in a default datatable - c#

I have a function like this in one of my classes and then I need to call it in another class and get the value in a default datatable.
public DataTable GetPrimaryKeyTables(string localServer, string userName, string password, string selectedDatabase)
{
// Create the datatable
DataTable dtListOfPrimaryKeyTables = new DataTable("tableNames");
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = localServer; ;
objConnectionString.UserID = userName;
objConnectionString.Password = password;
objConnectionString.InitialCatalog = selectedDatabase;
// Query to select primary key tables.
string selectPrimaryKeyTables = #"SELECT
TABLE_NAME
AS
TABLES
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE
CONSTRAINT_TYPE = 'PRIMARY KEY'
ORDER BY
TABLE_NAME";
// put your SqlConnection and SqlCommand into using blocks!
using(SqlConnection sConnection = new SqlConnection(objConnectionString.ConnectionString))
using(SqlCommand sCommand = new SqlCommand(selectPrimaryKeyTables, sConnection))
{
try
{
// Create the dataadapter object
SqlDataAdapter sDataAdapter = new SqlDataAdapter(selectPrimaryKeyTables, sConnection);
// Fill the datatable - no need to open the connection, the SqlDataAdapter will do that all by itself
// (and also close it again after it is done)
sDataAdapter.Fill(dtListOfPrimaryKeyTables);
dgResultView.DataSource = dtListOfPrimaryKeyTables;
}
catch(Exception ex)
{
//All the exceptions are handled and written in the EventLog.
EventLog log = new EventLog("Application");
log.Source = "MFDBAnalyser";
log.WriteEntry(ex.Message);
}
}
// return the data table to the caller
return dtListOfPrimaryKeyTables;
}
Can anyone help me in this, every time I try, the controls are not inherited from one class to another.

I am not sure what you mean by 'controls not inherited from one class to another'.
you will create an object of this class in your another class and call the method on it.
something like this
class class1
{
public DataTable GetPrimaryKeyTables(string localServer, string userName, string password, string selectedDatabase)
.......
........
return dtListOfPrimaryKeyTables;
}
class Class2
{
protected void BindControl(....)
{
DataTable dt = new class1().GetPrimaryKeyTables(......);
dgResultView.DataSource = dt;
dgResultView.DataBind();
}
}
Either you pass 'dgResultView' as a parameter to the method or you use the above code snippet. Controls are defined as 'Protected', hence they won't be accessible in the other class. dgResultView.DataSource = dtListOfPrimaryKeyTables; used in the function is not gonna work.
It is a good idea to have your connection string and other information in a config file and is accessed from there.

Related

Need advice on how to get data from a database into a list of objects, without knowing beforehand what database I will be connecting to

I'm trying to write a function in an MVC C# controller into which I can pass in the table name, server name, database name, username and password. This function is being called from an Ajax call, so it needs to return JSON. I'm using to using entity framework, so I'm sort of new to this - I've been trying to use SqlDataReader, and then automatically put all data return into a list of objects, which I can then return to the Ajax, but I'm not even getting close - all of the methods using SqlDataReader seem to require knowing what rows you want to select in advance, so I have no real clue what do to or try next. Has anybody got any advice on how to achieve this?
Basically, it's for a project I've been tasked with where someone can fill in a form with the connection string, and sql query, and the scripts will go to the controller and return the data. The user can then pick what column(s) they want to use, using dc.js, I will create whatever chart they chose based on whatever columns they chose, based on the returned data. It's melting me head...
This is something I have in a project:
/// <summary>
/// Get all of the SQL data from "tableName" using "connectionString"
/// </summary>
public static DataTable GetSqlDataAsDataTable(string tableName, string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(string.Format("SELECT * FROM [{0}]", tableName), connection))
{
cmd.CommandType = CommandType.Text;
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
using (DataTable dt = new DataTable())
{
try
{
sda.Fill(dt);
}
catch (Exception)
{
// handle it
}
return dt;
}
}
}
}
}
Once you have that, you can convert the DT to JSON as described in this other answer: https://stackoverflow.com/a/17398078/4842817
public static string GetJSON(string connectionString, string tableName)
{
try
{
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
SqlCommand command = new SqlCommand($"SELECT * FROM {tableName}", connection);
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
connection.Close();
string json = Newtonsoft.Json.JsonConvert.SerializeObject(dataTable.Rows);
return json;
}
catch { return string.Empty; }
}
The code above requires references to System.Data and System.Data.SqlClient as well as the open-source Nuget package called Newtonsoft.Json.
It will open up a connection based on the connection string provided, select all columns from the specified table and populate a DataTable object with this information.
Newtonsoft.Json's JsonConvert.SerializeObject(object) method will serialize the DataRowCollection (dataTable.Rows) to a JSON string to be returned.
I would use Dapper and Newtonsoft.Json from nuget and do it like this:
public string GetTableContentsAsJson(string serverName, string databaseName, string userName, string password, string tableName)
{
System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
builder["Data Source"] = serverName;
builder["integrated Security"] = false;
builder["Initial Catalog"] = databaseName;
builder["User ID"] = userName;
builder["Password"] = password;
Console.WriteLine(builder.ConnectionString);
using (var connection = new SqlConnection(builder.ConnectionString))
{
connection.Open();
var images = connection.Query($"SELECT * FROM {tableName}");
string s = JsonConvert.SerializeObject(images);
return s;
}
}
Hi Entity framework itself providing the freedom to choose databases dynamically. Write a procedure for fetching the column details and return the result, it will solve your issue.

Connection to SQL Server through ADO.NET - Empty Listbox

Trying to set up a connection to my local SQL Server Express instance so that I can display columns in a listbox. Th build runs fine and I can't see errors, but there is no data in the listbox. I have tested the query and that is fine. I am using NT Authentication to the database. Any ideas where I might have gone wrong?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void customers_SelectedIndexChanged(object sender, EventArgs e)
{
string commstring = "Driver ={SQL Server}; Server = DESKTOP-5T4MHHR\\SQLEXPRESS; Database = AdventureWorks2014; Trusted_Connection = Yes;";
string connstring = "SELECT FirstName, LastName FROM Person.Person";
SqlDataAdapter customerDataAdapater = new SqlDataAdapter(commstring, connstring);
DataSet customerDataSet = new DataSet();
customerDataAdapater.Fill(customerDataSet, "Person.Person");
DataTable customerDataTable = new DataTable();
customerDataTable = customerDataSet.Tables[0];
foreach (DataRow dataRow in customerDataTable.Rows)
{
customers.Items.Add(dataRow["FirstName"] + " (" + dataRow["LastName"] + ")");
}
}
}
I tested your code in a sample project here and I realized you passed the parameters to SqlDataAdapter constructor in a wrong order.
After changing the follow line:
SqlDataAdapter customerDataAdapater = new SqlDataAdapter(commstring, connstring);
by
SqlDataAdapter customerDataAdapater = new SqlDataAdapter(connstring, commstring);
the listbox was filled successfully.
Your connection string seems weird.....
Could you try using just this:
string commstring = "Server=DESKTOP-5T4MHHR\\SQLEXPRESS;Database=AdventureWorks2014;Trusted_Connection=Yes;";
Also: why are you first creating a DataSet, filling in a single set of data, and then extracting a DataTable from it?? This is unnecessarily complicated code - just use this instead:
SqlDataAdapter customerDataAdapater = new SqlDataAdapter(commstring, connstring);
// if you only ever need *one* set of data - just use a DataTable directly!
DataTable customerDataTable = new DataTable();
// Fill DataTable with the data from the query
customerDataAdapater.Fill(customerDataTable);
Update: I would really rewrite your code to something like this:
// create a separate class - call it whatever you like
public class DataProvider
{
// define a method to provide that data to you
public List<string> GetPeople()
{
// define connection string (I'd really load that from CONFIG, in real world)
string connstring = "Server=MSEDTOP;Database=AdventureWorks2014;Trusted_Connection=Yes;";
// define your query
string query = "SELECT FirstName, LastName FROM Person.Person";
// prepare a variable to hold the results
List<string> entries = new List<string>();
// put your SqlConnection and SqlCommand into "using" blocks
using (SqlConnection conn = new SqlConnection(connstring))
using (SqlCommand cmd = new SqlCommand(query, conn))
{
conn.Open();
// iterate over the results using a SqlDataReader
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// get first and last name from current row of query
string firstName = rdr.GetFieldValue<string>(0);
string lastName = rdr.GetFieldValue<string>(1);
// add entry to result list
entries.Add(firstName + " " + lastName);
}
rdr.Close();
}
conn.Close();
}
// return the results
return entries;
}
}
And in your code-behind, you only need to do something like this:
protected override void OnLoad(.....)
{
if (!IsPostback)
{
List<string> people = new DataProvider().GetPeople();
customers.DataSource = people;
customers.DataBind();
}
}
but I still don't understand what you were trying to when the SelectedIndexChanged event happens.....

c# and stored procedures, unique code per SProc?

I'm writing an application which first connect to the database and retrieves a dt containing a list of all the stored procedures, inputs and their associated datatypes. The user then selected a SProc from the combobox and has to enter in the necessary inputs. The app will then connect to the database and run the selected SProc with the user specified inputs and return the results in a datatable.
What I'm unsure about is if I need to write a specific method for each SProc. I'm assuming so since I don't see how I could state what the parameters are otherwise.
Apologies for not making this clear the first time. Let me know if this still isn't clear enough.
Example is shown below (this is someone else's code)
public static GetDaysDTO GetDays(int offset)
{
GetDaysDTO ret = new GetDaysDTO { TODAY = DateTime.Now, TOMORROW = new DateTime(2012, 01, 01) };
SqlConnection con = new System.Data.SqlClient.SqlConnection(#"Server = FrazMan-pc\Programming; Database = master; Trusted_Connection = True");
SqlCommand cmd = new System.Data.SqlClient.SqlCommand
{
CommandText = "GetDays",
CommandType = System.Data.CommandType.StoredProcedure,
CommandTimeout = 1,
Connection = con,
Parameters = { new System.Data.SqlClient.SqlParameter("#offset", System.Data.SqlDbType.Int) { Value = offset } }
};
using (con)
{
con.Open();
using (System.Data.SqlClient.SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
ret.TODAY = DateTime.Parse(reader[0].ToString());
ret.TOMORROW = DateTime.Parse(reader["TOMORROW"].ToString());
}
}
}
return ret;
}
What you're looking for is a design pattern called Factory and a way to tell which typed data table to create on each SP call
If you have the list of the parameters for each procedure, u could instantiate the Parameters object via a loop:
This class will be used to fill the params of the sp received from the db
class ParamData
{
public object Data;
public SqlDbType type;
public string ParamName;
}
and then later on, when calling the sp, u should also pass thie ParamData object to the method, and used it to fill the params of ur sp dynamicly in a loop:
List<ParamData> list = new List<ParamData>();
//initialize command here as u did
SqlCommand cmd;
foreach (ParamData param in list)
{
SqlParameter sqlParam = new SqlParameter(param.ParamName, param.type);
sqlParam.Value = param.Data;
cmd.Parameters.Add(sqlParam);
}
//execute the command
//fill the datatable with result
DataTable dt = GetTableBySPName("GetDays");
SqlDataReader reader = cmd.ExecuteReader();
dt.Load(reader);
The only thing you need to add is the mapping between ur typed datatables and the returned table by the procedure.
You can add a method to do this:
private DataTable GetTableBySPName(string name)
{
DataTable dt = null;
switch (name)
{
case "GetDays":
{
dt = new GetDatsDTO();
break;
}
}
return dt;
}

Defining function in one class and calling in other class is not inheriting the controls

I have defined the function in one class like
public static DataSet GetAllPrimaryKeyTables()
{
//An instance of the connection string is created to manage the contents of the connection string.
using(var sConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString"]))
{
//To Open the connection.
sConnection.Open();
//Query to select the table_names that have PRIMARY_KEYS.
string selectPrimaryKeys = #"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME <> 'dtProperties'
ORDER BY TABLE_NAME";
//Create the command object
using(var sCommand = new SqlCommand(selectPrimaryKeys, sConnection))
{
try
{
//Create the dataset.
DataSet dsPrimaryKeyTables = new DataSet("INFORMATION_SCHEMA.TABLE_CONSTRAINTS ");
//Create the dataadapter object.
SqlDataAdapter daPrimaryKeyTables = new SqlDataAdapter(selectPrimaryKeys, sConnection);
//Provides the master mapping between the sourcr table and system.data.datatable
daPrimaryKeyTables.TableMappings.Add("Table", "INFORMATION_SCHEMA.TABLE_CONSTRAINTS ");
//Fill the dataadapter.
daPrimaryKeyTables.Fill(dsPrimaryKeyTables);
//Bind the result combobox with non primary key table names
DataViewManager dsvPrimaryKeyTables = dsPrimaryKeyTables.DefaultViewManager;
return dsPrimaryKeyTables;
}
catch(Exception ex)
{
//Handles the exception and log that to the EventLog with the original message.
EventLog log = new EventLog("Application");
log.Source = "MFDBAnalyser";
log.WriteEntry(ex.Message);
return null;
}
finally
{
//checks whether the connection is still open.
if(sConnection.State != ConnectionState.Closed)
{
sConnection.Close();
}
}
}
}
}
And now how should i code so that I can call that function in another class in a dafault dataset.
Will anybody please help me??
Making this function an Extension Method on DataSet type will sole your problem if I understand you,
You will use something like this.
Dataset myPrimaryKeyDataset = YourClassName.GetAllPrimaryKeyTables();
Hope this helps.

Binding data to a rich textbox control i windows application

Hi All,
I am currently binding my data in a datagrid like this
public DataTable GetAllPrimaryKeyTables(string localServer, string userName, string password, string selectedDatabase)
{
// Create the datatable
DataTable dtListOfPrimaryKeyTables = new DataTable("tableNames");
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = localServer; ;
objConnectionString.UserID = userName;
objConnectionString.Password = password;
objConnectionString.InitialCatalog = selectedDatabase;
// Query to select primary key tables.
string selectPrimaryKeyTables = #"SELECT
TABLE_NAME
AS
TABLES
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE
CONSTRAINT_TYPE = 'PRIMARY KEY'
AND
TABLE_NAME <> 'dtProperties'
ORDER BY
TABLE_NAME";
// put your SqlConnection and SqlCommand into using blocks!
using(SqlConnection sConnection = new SqlConnection(objConnectionString.ConnectionString))
using(SqlCommand sCommand = new SqlCommand(selectPrimaryKeyTables, sConnection))
{
try
{
// Create the dataadapter object
SqlDataAdapter sDataAdapter = new SqlDataAdapter(selectPrimaryKeyTables, sConnection);
// Fill the datatable - no need to open the connection, the SqlDataAdapter will do that all by itself
// (and also close it again after it is done)
sDataAdapter.Fill(dtListOfPrimaryKeyTables);
}
catch(Exception ex)
{
//All the exceptions are handled and written in the EventLog.
EventLog log = new EventLog("Application");
log.Source = "MFDBAnalyser";
log.WriteEntry(ex.Message);
}
}
// return the data table to the caller
return dtListOfPrimaryKeyTables;
}
And then giving the datasource as this
protected void GetPrimaryKeyTables()
{
DataTable dtPrimaryKeys = new DataAccessMaster().GetAllPrimaryKeyTables(txtHost.Text, txtUsername.Text, txtPassword.Text, Convert.ToString(cmbDatabases.SelectedValue));
dgResultView.DataSource = dtPrimaryKeys;
}
But now I need to bind the datatable to a richtextbox control available in the toolbox.
Waiting for reply!!!
How to do that??
I don't think you can bind a dataTable to a RichTextBox "as is" because the structure of the two elements are intrinsically different. you can't "magically" bind a multi-element table to a single element string-containing element. IMHO you should extract the string from DB and put it into (or bind it as a string) your RichTextBox Control.

Categories