Getting information about DataRelations in a DataSet - c#

Using FillSchema-method of the data adapter I obtain the table structure
using (SqlConnection sqlConn = new SqlConnection(connectionString))
{
var dataAdapter = new SqlDataAdapter();
var dataSet = new DataSet();
sqlConn.Open();
string sqlSelectCommand = "select * from Projects;\nselect * from Staff"
dataAdapter.SelectCommand = new SqlCommand(sqlSelectCommand, sqlConn);
dataAdapter.FillSchema(dataSet, SchemaType.Source);
dataAdapter.Fill(dataSet);
dataSet.Tables[0].TableName = "Projects";
dataSet.Tables[1].TableName = "Staff";
// create relations between the tables
// is there an alternative way?
var relation = new DataRelation("FK_Projects_Staff", dataSet.Tables["Staff"].Columns["ID"], dataSet.Tables["Projects"].Columns["Responsible_ID"], true);
dataSet.Relations.Add(relation);
// do some manipulations on data using projectsDataAdapter and staffDataAdapter
// ...
}
Is there a similar way to fill the relations of all relevant tables?

Please see if the below link can help you.
http://csharptutorial.com/how-to-create-a-dataset-programmatically/

Related

How to copy Access table to SQL table in C#?

As title says I've used odbcconnection to sqlconnection and for the life of me cant get it to work.. Copied a bunch of code from this site but cant get them both to work.
The program just hangs so maybe I am doing something wrong, but would appreciate maybe a bare bones template that i could just fill in the connection details and bulk copy the table to table..
using (OdbcConnection myConnection = new OdbcConnection())
{
string myConnectionString = #"Driver={Microsoft Access Driver (*.mdb)};" +
"Dbq=//####/data/Toronto/wrkgrp/wrkgrp30/Business Risk Oversight and Control/DATA INTEGRITY/CDE/CDE Testing Portal Requirements/Migration Requirements/RCM/Mutual Funds/Mutual Funds.mdb;";
myConnection.ConnectionString = myConnectionString;
myConnection.Open();
//execute queries, etc
OdbcCommand cmd = myConnection.CreateCommand();
cmd.CommandText = "SELECT * FROM RCM_MF_New_Accounts_Samples";
OdbcDataReader reader = cmd.ExecuteReader(); // close conn after complete
DataTable myDataTable = new DataTable();
myDataTable.Load(reader);
//myConnection.Close();
string destinationConnectionString = "Data Source=####;Initial Catalog=DYOF_STAGING_BROC;User ID=;Password=;Connection Timeout=999";
SqlConnection destination = new SqlConnection(destinationConnectionString);
SqlBulkCopy bulkData;
//destination.Open();
Exception ex = null;
try
{
Console.WriteLine("step1");
bulkData = new SqlBulkCopy(destinationConnectionString, SqlBulkCopyOptions.FireTriggers);
bulkData.BulkCopyTimeout = 1;
bulkData.DestinationTableName = "Load_CTR_Sample_Account_Opening2";
bulkData.WriteToServer(myDataTable);
bulkData.Close();
Console.WriteLine("moved from here to there");
reader.Close();
//destination.Close();
}
catch (Exception e)
{
ex = e;
}
I actually wrote an ORM to make this kind of task easier.
var accessDS = new AccessDataSource(connectionString1);
var dt = accessDS.From("RCM_MF_New_Accounts_Samples").ToDataTable().Execute();
var sqlDS = new SqlServerDataSource(connectionString2);
sqlDS.InsertBulk("Load_CTR_Sample_Account_Opening2", dt).Execute();
This does not work for .NET Core.
Packages:
https://www.nuget.org/packages/Tortuga.Chain.Access/
https://www.nuget.org/packages/Tortuga.Chain.SqlServer
Read the data from Access into a DataTable:
string strConnect = #"Provider=Microsoft.ACE.OLEDB.12.0;data source=D:\Temp\MyDB.accdb";
DataTable dt = new DataTable();
using (OleDbConnection con = new OleDbConnection(strConnect))
{
OleDbCommand cmd = new OleDbCommand("SELECT * FROM MyTable", con);
con.Open();
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
}
Then use SqlBulkCopy to update SQL:
string strConnect = #"Data Source=GRIFFPC\SQLEXPRESS;Initial Catalog=Testing;Integrated Security=True";
using (SqlConnection con = new SqlConnection(strConnect))
{
con.Open();
using (SqlBulkCopy bulk = new SqlBulkCopy(con))
{
bulk.DestinationTableName = "Test";
bulk.WriteToServer(dt);
}
}
Of course, there is a much easier way to go straight from Access to SQL Server, using VBA, SQL , or other methods.
https://support.office.com/en-us/article/import-or-link-to-data-in-an-sql-server-database-a5a3b4eb-57b9-45a0-b732-77bc6089b84e
https://www.sqlshack.com/six-different-methods-to-copy-tables-between-databases-in-sql-server/
Here's a basic example of bulk insert.
public void BulkInsert(DataTable employees)
{
if (employees == null)
throw new ArgumentNullException(nameof(employees), $"{nameof(employees)} is null.");
using (var con = OpenConnection())
using (var sbc = new SqlBulkCopy(con))
{
sbc.DestinationTableName = "HR.Employee";
foreach (DataColumn column in employees.Columns)
sbc.ColumnMappings.Add(column!.ColumnName, column.ColumnName);
sbc.WriteToServer(employees);
}
}
Note the foreach (DataColumn column in employees.Columns) loop. This is required so that it knows the column names are the same in the source and the target table. (If they're not the same, manually map them in the same fashion.)
Source: https://grauenwolf.github.io/DotNet-ORM-Cookbook/BulkInsert.htm#ado.net
Following option need to verify
1) Column Name should be the same.
2) verify the column length.
3) verify the data type.

dataset relation in c# for two columns

I would really appreciate a help in this code. I have a DataSet with two tables; I need to create a relation based on two columns as primary key:
public DataSet GetAll()
{
string sql = $#"SELECT * FROM Journal ORDER BY JvNO, cYear;
SELECT * FROM JournalDetail ORDER BY JvNO, cYear";
using (SqlConnection connection = new SqlConnection(GlobalConfig.ConnString()))
{
connection.Open();
SqlCommand cmd = new SqlCommand(sql, connection);
SqlDataAdapter da = new SqlDataAdapter(sql, connection);
DataSet ds = new DataSet();
da.Fill(ds);
ds.Relations.Add("Journal_Batch", new DataColumn[] { ds.Tables[0].Columns["JvNO"], ds.Tables[0].Columns["cYear"] },
new DataColumn[] { ds.Tables[1].Columns["JvNO"], ds.Tables[1].Columns["cYear"] });
return ds;
}
}
Currently, I'm doing it like this and it's working but I need it with DataSet relation:
public DataSet GetJournalByID(int JVNO, int cYear)
{
string sql = $#"SELECT * FROM Journal WHERE JvNO = { JVNO } and cYear = { cYear };
SELECT * FROM JournalDetail WHERE JvNO = { JVNO } and cYear = { cYear };";
using (SqlConnection connection = new SqlConnection(GlobalConfig.ConnString()))
{
connection.Open();
SqlCommand cmd = new SqlCommand(sql, connection);
SqlDataAdapter da = new SqlDataAdapter(sql, connection);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
}
I don't know what's wrong with first code, as it returns all matching JvNO or Year.
i want to use the first one to fill two grids as follow:
private void GetData()
{
DataSet currentDs = new DataSet();
grdJournalDetails.DataSource = null;
grdJournal.DataSource = null;
JournalConnector journalConnection = new JournalConnector();
currentDs = journalConnection.GetAll();
grdJournal.DataSource = currentDs.Tables[0];
grdJournalDetails.DataSource = currentDs.Tables[1];
}
then with each row selected from grdJournal to display grdJournalDetails with related data without calling each time the second snippet of code.
i used Dapper and i'm familiar with it, but with devexpress grid, it have to be a datatable to use the event gvJournal_FocusedRowChanged, otherwise datarow returns always null;
Thanks for any suggestion.

dataGridView not showing data after DataSource

I am new to C# and have simple method to show data from a table DimCustomer. I am calling this method from a button but its not displaying data. Although when i debug my code i can see data, but not displaying it. Any suggestions please
private void ShowGridData()
{
// create a connection object
string ConnectionString = "Integrated Security=SSPI;" +
"database=AdventureWorksDW2012;" + "server=DESKTOP-L9L3SMT\\SQL2K12;";
SqlConnection conn = new SqlConnection(ConnectionString);
// open the connection
conn.Open();
// Create a DataTableMapping object
DataTableMapping myMapping = new DataTableMapping("DimCustomer", "mapCustomer");
SqlDataAdapter adapter = new SqlDataAdapter("Select * FROM DimCustomer where LastName='yang' and BirthDate='1966-04-08'", conn);
// Call DataAdapter's TableMappings.Add method
adapter.TableMappings.Add(myMapping);
// Create a DataSet object and Call DataAdapter's Fill method
DataSet ds = new DataSet();
adapter.Fill(ds, "DimCustomer");
dataGridView1.ColumnCount = 0;
dataGridView1.DataSource = ds.DefaultViewManager;
}
Can you please try this instead?
dataGridView1.DataSource = ds.Tables[0];

Creating a new DataRow into an existing DataTable

Greets! I am trying to create a DataRow and add it to an existing DataSet/DataTable. The problem I am running into is that the tables do not seem to be propagating correctly. I know the table exists yet it won't give me anything but null in return. Any ideas?
Code:
var TownDataSet = new DataSet("newDataSet");
var checkDataSet = new DataSet();
var checkDataTable = new DataTable();
var dataTableName = "someDataSet";
checkDataSet = TownDataSet.Clone();
checkDataTable = TownDataSet.Tables[dataTableName];
Console.WriteLine("STEP 4 " + checkDataSet.DataSetName);
Console.WriteLine("STEP 5 " + checkDataSet.Tables.Count);
Console.WriteLine("STEP 6 " + checkDataTable.TableName);
Error when I get to Step 6:
STEP 4 newDataSet
STEP 5 7
DataTableInsertTemp: System.NullReferenceException: Object reference not set to an instance of an object.
Let's analyze:
var TownDataSet = new DataSet("newDataSet");
var checkDataSet = new DataSet();
var checkDataTable = new DataTable();
var dataTableName = "someDataSet";
checkDataSet = TownDataSet.Clone();
checkDataTable = TownDataSet.Tables[dataTableName];
Where:
checkDataSet is a new DataSet containing 0 tables;
checkDataTable is a new DataTable contained in no DataSet
So:
TownDataSet.Tables is an empty collection
TownDataSet.Tables[dataTableName] is null
Try this instead:
var dataTableName = "someDataSet";
var TownDataSet = new DataSet("newDataSet");
var checkDataSet = new DataSet();
/* add a new DataTable to the DataSet.Tables collection */
checkDataSet.Tables.Add(new DataTable(dataTableName));
/* maybe you need to add some columns too */
checkDataSet.Tables[dataTableName].Columns.Add(new DataColumn("columnA", typeof(int)));
checkDataSet.Tables[dataTableName].Columns.Add(new DataColumn("columnB", typeof(string)));
/* create and initialize a new DataRow for the Tables[dataTableName] table */
var r = TownDataSet.Tables[dataTableName].NewRow();
r["columnA"] = 1;
r["columnB"] = "Some value";
/* add it to the Tables[dataTableName].Rows collection */
TownDataSet.Tables[dataTableName].Rows.Add(r);
EDIT
There are several ways to map a db into a dataset. I can suggest you a few:
POCO - Plain Old CLR Object. That is create an entity class for each table, mapping the table's fields into the class's properties.
Object-Relational Mapping. It is a framework layer that maps database tables into classes. A C# implementation is NHibernate.
ADO.NET Tables Schema. You can use the ADO.NET capabilities to import the database's tables schema definition into a dataset using the DataAdapter class.
Here a basic implementation:
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable("myTable"));
da.FillSchema(ds.Tables["mytable"], SchemaType.Source);
var dataTableName = "someDataSet";
var TownDataSet = new DataSet("newDataSet");
var checkDataSet = new DataSet();
/* add a new DataTable to the DataSet.Tables collection */
checkDataSet.Tables.Add(new DataTable(dataTableName));
/*
* Fit the sql statement and the connection string depending on your scenario
* Set the *Command, *Connection and *DataAdapter actual provider
*/
SqlCommand cmd = new SqlCommand("select * from myTable");
SqlConnection conn = new SqlConnection("my connection string");
SqlDataAdapter da = new SqlDataAdapter();
cmd.Connection = conn;
da.SelectCommand = cmd;
/* that's it: the datatable is now mapped with the corresponding db table structure */
da.FillSchema(checkDataSet.Tables[dataTableName], SchemaType.Source);

DataSet, SqlDataAdapter, Multiple select returns one table

I would like to make one call (containing several SELECT statement) to the database and then databind the results to multiple components.
I'm using a DataSet and SqlDataAdapter to fill tables that are then bound to components.
Problem is the results of the first SELECT statement are put into both tables so I get a "'System.Data.DataRowView' does not contain a property..." error when I try to use the second lot of data on the second component.
Have I misunderstood how this is meant to work?
DataSet ds = new DataSet();
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["myString"].ConnectionString);
StringBuilder topicDropDownListSQL = new StringBuilder();
topicDropDownListSQL.Append("SELECT topic.topic_ID, topic.topic_title FROM FPL2012_TOPIC as topic WHERE topic.topic_isEnabled = 1;");
topicDropDownListSQL.Append("SELECT explain.itemExplanationType_ID, explain.itemExplanationType_type FROM FPL2012_ITEM_EXPLANATION_TYPE as explain;");
SqlDataAdapter da = new SqlDataAdapter(topicDropDownListSQL.ToString(), connection);
ds.Tables.Add("Topics");
ds.Tables.Add("ExplainType");
ds.EnforceConstraints = false;
ds.Tables["Topics"].BeginLoadData();
da.Fill(ds.Tables[0]);
ds.Tables["Topics"].EndLoadData();
ds.Tables["ExplainType"].BeginLoadData();
da.Fill(ds.Tables[1]);
ds.Tables["ExplainType"].EndLoadData();
topicDropDownList.DataValueField = "topic_ID";
topicDropDownList.DataTextField = "topic_title";
topicDropDownList.DataSource = ds.Tables["Topics"];
topicDropDownList.DataBind();
explanationTypeDropDownList.DataValueField = "itemExplanationType_ID";
explanationTypeDropDownList.DataTextField = "itemExplanationType_type";
explanationTypeDropDownList.DataSource = ds.Tables["ExplainType"];
explanationTypeDropDownList.DataBind();
connection.Close();
You can use this acces the tables by there indexes not by there names
DataSet ds = new DataSet();
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["myString"].ConnectionString);
String qry="SELECT topic_ID,topic_title FROM FPL2012_TOPIC WHERE topic_isEnabled = 1; SELECT itemExplanationType_ID, itemExplanationType_type FROM FPL2012_ITEM_EXPLANATION_TYPE ";
SqlDataAdapter da = new SqlDataAdapter(qry, connection);
da.Fill(ds)
topicDropDownList.DataValueField = "topic_ID";
topicDropDownList.DataTextField = "topic_title";
topicDropDownList.DataSource = ds.Tables[0];
topicDropDownList.DataBind();
explanationTypeDropDownList.DataValueField = "itemExplanationType_ID";
explanationTypeDropDownList.DataTextField = "itemExplanationType_type";
explanationTypeDropDownList.DataSource = ds.Tables[1];
explanationTypeDropDownList.DataBind();
connection.Close();
OK, I tried using a datareader next, didn't expect it to work but it does! I can make multiple select statements and then fill multiple componenets. I'm not marking this as an answer as I still think it would be useful to know how to do it using the dataset.
The new code that worked for me (in case it is useful):
string connectionString = WebConfigurationManager.ConnectionStrings["myString"].ConnectionString;
SqlConnection connection = new SqlConnection(connectionString);
StringBuilder sql = new StringBuilder();
sql.Append("SELECT topic.topic_ID, topic.topic_title FROM FPL2012_TOPIC as topic WHERE topic.topic_isEnabled = 1;");
sql.Append("SELECT explain.itemExplanationType_ID, explain.itemExplanationType_type FROM FPL2012_ITEM_EXPLANATION_TYPE as explain;");
SqlCommand command = new SqlCommand(sql.ToString(), connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
topicDropDownList.DataSource = reader;
topicDropDownList.DataValueField = "topic_ID";
topicDropDownList.DataTextField = "topic_title";
topicDropDownList.DataBind();
reader.NextResult();
explanationTypeDropDownList.DataSource = reader;
explanationTypeDropDownList.DataValueField = "itemExplanationType_ID";
explanationTypeDropDownList.DataTextField = "itemExplanationType_type";
explanationTypeDropDownList.DataBind();
reader.Close();
connection.Close();

Categories