This is the first time I am using DataSet. Below is my code
var transactionSet = new ModelExecutionContext()
{
TransactionSet = new DataSet()
{
Tables = { new DataTable()
{
TableName = "transaction_history"
}
}
}
};
transactionSet.TransactionSet.Tables["transaction_history"].Columns.Add().ColumnName = "retailer_reference_id";
var retailerReferenceIdRow = transactionSet.TransactionSet.Tables["transaction_history"].NewRow();
retailerReferenceIdRow["retailer_reference_id"] = 8;
transactionSet.TransactionSet.AcceptChanges();
I am unit testing a method in a class which has the datasets. I am trying to mock those datasets. I thought transactionSet.TransactionSet.AcceptChanges(); will save the changes into the DataSet, but in the execution, I am getting context?.TransactionSet?.Tables["transaction_history"]?.Rows.Count = 0
Is anything incorrect with my code?
After you created object of row you need to add row to table.
transactionSet.TransactionSet.Tables["transaction_history"].Rows.Add(retailerReferenceIdRow);
Related
I'm trying to write a method in C# which when passed a System.Data.DataTable and destination database and table name, inserts the data.
I have this working well for SQL Server destinations, but for Teradata destinations the method I have come up with is incredibly slow by comparison (~70x time), which for some of the data my users will need to upload is unacceptable.
I'm posting both sets of code below, hoping someone can help me with a better method for Teradata please?
Teradata (using Teradata.Client.Provider library):
public static void UploadTDData(DataTable dtLogData, string destination)
{
// Get destination table structure without data
var query = string.Format("SELECT * FROM {0} where 0 = 1", destination);
using (TdDataAdapter insertAdapter = new TdDataAdapter(query, myTeradataConnection))
{
DataTable dt = new System.Data.DataTable();
insertAdapter.Fill(dt);
foreach (DataRow row in dtLogData.Rows)
{
DataRow newRow = dt.NewRow();
newRow.ItemArray = row.ItemArray;
dt.Rows.Add(newRow);
}
TdCommandBuilder builder = new TdCommandBuilder(insertAdapter);
//No limit on batch size
insertAdapter.UpdateBatchSize = 0;
insertAdapter.Update(dt);
}
}
SQL Server:
public static void UploadData(DataTable dtLogData, string destination)
{
using (System.Data.SqlClient.SqlBulkCopy sqlBulkCopy = new System.Data.SqlClient.SqlBulkCopy(mySQLConnection))
{
sqlBulkCopy.DestinationTableName = destination;
sqlBulkCopy.WriteToServer(dtLogData);
}
}
my problem is very common, but I have not found any solution.
This is my code:
public async Task<QueryResult> RollbackQuery(ActionLog action)
{
var inputParameters = JsonConvert.DeserializeObject<Parameter[]>(action.Values);
var data = DeserailizeByteArrayToDataSet(action.RollBackData);
using (var structure = PrepareStructure(action.Query, action.Query.DataBase, inputParameters))
{
//_queryPlanner is the implementor for my interface
return await _queryPlanner.RollbackQuery(structure, data);
}
}
I need to load DataTable (from whereever) and replace data to database. This is my Rollback function. This function use a "CommandStructure" where I've incapsulated all SqlClient objects. PrepareStructure initialize all objects
//_dataLayer is an Helper for create System.Data.SqlClient objects
//ex: _dataLayer.CreateCommand(preSelect) => new SqlCommand(preSelect)
private CommandStructure PrepareStructure(string sql, string preSelect, DataBase db, IEnumerable<Parameter> inputParameters)
{
var parameters = inputParameters as IList<Parameter> ?? inputParameters.ToList();
var structure = new CommandStructure(_logger);
structure.Connection = _dataLayer.ConnectToDatabase(db);
structure.SqlCommand = _dataLayer.CreateCommand(sql);
structure.PreSelectCommand = _dataLayer.CreateCommand(preSelect);
structure.QueryParameters = _dataLayer.CreateParemeters(parameters);
structure.WhereParameters = _dataLayer.CreateParemeters(parameters.Where(p => p.IsWhereClause.HasValue && p.IsWhereClause.Value));
structure.CommandBuilder = _dataLayer.CreateCommandBuilder();
structure.DataAdapter = new SqlDataAdapter();
return structure;
}
So, my function uses SqlCommandBuilder and DataAdapter to operate on Database.
PreSelectCommand is like "Select * from Purchase where CustomerId = #id"
The table Purchase has one primaryKey on ID filed
public virtual async Task<QueryResult> RollbackQuery(CommandStructure cmd, DataTable oldData)
{
await cmd.OpenConnectionAsync();
int record = 0;
using (var cmdPre = cmd.PreSelectCommand as SqlCommand)
using (var dataAdapt = new SqlDataAdapter(cmdPre))
using (var cmdBuilder = new SqlCommandBuilder(dataAdapt))
{
dataAdapt.UpdateCommand = cmdBuilder.GetUpdateCommand();
dataAdapt.DeleteCommand = cmdBuilder.GetDeleteCommand();
dataAdapt.InsertCommand = cmdBuilder.GetInsertCommand();
using (var tbl = new DataTable(oldData.TableName))
{
dataAdapt.Fill(tbl);
dataAdapt.FillSchema(tbl, SchemaType.Source);
tbl.Merge(oldData);
foreach (DataRow row in tbl.Rows)
{
row.SetModified();
}
record = dataAdapt.Update(tbl);
}
}
return new QueryResult
{
RecordAffected = record
};
}
I Execute the code and I don't have any errors, but the data are not updated.
variable "record" contain the right number of modified (??) record, but..... on the table nothing
can someone help me?
EDIT 1:
With SQL Profiler I saw that no query is executed on DB. Only select query on .Fill(tbl) command.
EDIT 2:
Now I have made one change:
tbl.Merge(oldData) => tbl.Merge(oldData, true)
so I see perform the expected query but, with reversed parameters.
UPDATE Purchase SET price=123 where id=6 and price=22
instead of
UPDATE Purchase SET price=22 where id=6 and price=123
I am using two Datasets on this page 1.DsCountry(in BindCountry()) and 2.DsState(in BindState()) but data from the database is getting filled only in DsCountry not in DsState but when BindCountry() is commented DsState is working.
public void BindCountry()
{
objCountry.SortOn = Convert.ToString(ViewState["SortOn"]);
objCountry.SortBy = Convert.ToString(ViewState["SortBy"]);
DataSet DsCountry = objCountry.GetAllCountryDetails();
ddlCntry.DataSource = DsCountry.Tables[0];
ddlCntry.DataValueField = "CountryId";
ddlCntry.DataTextField = "CountryName";
ddlCntry.DataBind();
}
public void BindState()
{
objState.CountryId = int.Parse(ddlCntry.SelectedItem.Value);
objState.StateName = txtState.Text.Trim();
objState.SortOn = ViewState["SortOnState"].ToString();
objState.SortBy = ViewState["SortByState"].ToString();
DataSet DsState = objState.getStates();
gvState.DataSource = DsState;
gvState.DataBind();
}
In here:
public void BindState()
{
objState.CountryId = int.Parse(ddlCntry.SelectedItem.Value);
objState.StateName = txtState.Text.Trim();
objState.SortOn = ViewState["SortOnState"].ToString();
objState.SortBy = ViewState["SortByState"].ToString();
DataSet DsState = objState.getStates();
gvState.DataSource = DsState;
gvState.DataBind();
}
on this line:
gvState.DataSource = DsState;
if this is a dataset (implies it has multiple tables in it), then you need to specify a specific table you want to bind to, just like in your country method:
ddlCntry.DataSource = DsCountry.Tables[0];
will become this:
gvState.DataSource = DsState.Tables[0];
Assuming you return only one table in the dataset.
otherwise its like: go get me something I do not know what. :)
Your BindState Code should be like this
public void BindState()
{
objState.CountryId = int.Parse(ddlCntry.SelectedItem.Value);
objState.StateName = txtState.Text.Trim();
objState.SortOn = ViewState["SortOnState"].ToString();
objState.SortBy = ViewState["SortByState"].ToString();
DataSet DsState = objState.getStates();
gvState.DataSource = DsState.Tables[0];
gvState.DataBind();
}
You can apply more than 1 dataset in 1 page.
I am new to C# and ASP .NET programming. I am making a crystal report in .net. I setup Dataset and DataTable. For report sources.
I am getting data from a linq query. and after that I am populating them in a instance of Dataset. I use debugger and it shows that I have data from the query. But my crystal reeport just shows the column heading not the column data.
Here is my code:
private void ViewReport()
{
DataSet1 Dataset = new DataSet1();
DataTable rptTable = Dataset.Tables["Emp_info"];
DataTable rptTab = Dataset.Tables["Attendance_table"];
Ind_attendance_rpt rptAtd = new Ind_attendance_rpt();
DataRow dataRow1; // declaring Row of dataset
DataRow dataRow2;
//IndividualAttendance rptAtt = new IndividualAttendance();
var rport = from att in db.Attendance_tables
join emp in db.Emp_infos on att.Login_id equals emp.ID
orderby att.Id
select new
{
att.Id,
emp.Emp_name,
emp.ID,
emp.Designation,
emp.Dept,
att.Entry_time,
att.Exit_time,
att.Status,
att.Date
};
Dataset.Tables["Emp_info"].Clear();
Dataset.Tables["Attendance_table"].Clear();
foreach (var rt in rport)
{
dataRow1 = rptTable.NewRow();
dataRow2 = rptTab.NewRow();
dataRow2["Id"] = rt.Id;
dataRow1["Emp_name"] = rt.Emp_name;
dataRow1["Designation"] = rt.Designation;
dataRow1["Dept"] = rt.Dept;
dataRow2["Entry_time"] = rt.Entry_time;
dataRow2["Exit_time"] = rt.Exit_time;
dataRow2["Status"] = rt.Status;
dataRow2["Date"] = rt.Date;
dataRow2["Login_id"] = rt.ID;
Dataset.Tables["Emp_info"].Rows.Add(dataRow1);
Dataset.Tables["Attendance_table"].Rows.Add(dataRow2);
}
rptAtd.SetDataSource(Dataset);
CrystalReportViewer1.ReportSource = rptAtd;
}
Can anyone tell me the reason?
Here is the result I am getting right now:
Debug Image:
Try to call Refresh on the report after setting the ReportSource
CrystalReportViewer1.Refresh();
you may have to use ToList() on your linq as well;
Would someone kindly assist me with the following? I have two DataGridView objects that each display a DataTable, where the two datatables are related with the following code:
DataSet dSet = new DataSet();
DataTable ParentList = ListToDataTable(_listOfAllAlbumObjects);
DataTable ChildList = ListToDataTable(_listOfAllTrackObjects);
dSet.Tables.AddRange(new DataTable[]{ParentList, ChildList});
DataColumn parentRelationColumn = ParentList.Columns["AlbumId"];
DataColumn childRelationColumn = ChildList.Columns["AlbumId"];
dSet.Relations.Add("ParentToChild", parentRelationColumn, childRelationColumn);
ParentDataGridView.DataSource = dSet;
ParentDataGridView.DataMember = "ParentList";
ChildDataGridView.DataSource = ???;
ChildDataGridView.DataMember = "ParentToChild";
Both DataTables are actually List<> converted to DataTables with the following:`
public static DataTable ListToDataTable<T>( IList<T> data)
{
var props = TypeDescriptor.GetProperties(typeof(T));
var table = new DataTable();
for (var i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, prop.PropertyType);
}
var values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{ values[i] = props[i].GetValue(item); }
table.Rows.Add(values);
}
return table;
}
Initially it appears that the each DataGridView displays the data appropriately; however the child DataGridView does not update with any change of record in the parent DataGridView.
I see that the tables need to be interconnected through the binding-source; however I don't believe there is a true binding-source here.
Could someone please steer me in the right direction? Thanks.
There's an MSDN article showing what you want to do:
How to: Create a Master/Detail Form Using Two Windows Forms DataGridView Controls
Here's how this might work for you:
Either through the designer or through code add two BindingSources to your project: parentBindingSource and childBindingSource. Then try this in place of the code you have.
// Associate your BSs with your DGVs.
ParentDataGridView.DataSource = parentBindingSource;
ChildDataGridView.DataSource = childBindingSource;
// (Most of) your code here:
DataSet dSet = new DataSet();
DataTable ParentList = ListToDataTable(_listOfAllAlbumObjects);
DataTable ChildList = ListToDataTable(_listOfAllTrackObjects);
dSet.Tables.AddRange(new DataTable[]{ParentList, ChildList});
DataColumn parentRelationColumn = ParentList.Columns["AlbumId"];
DataColumn childRelationColumn = ChildList.Columns["AlbumId"];
dSet.Relations.Add("ParentToChild", parentRelationColumn, childRelationColumn);
// Let's name this DT to make clear what we're referencing later on.
ParentList.TableName = "ParentListDT";
// Rather than set the data properties on your DGVs, set them in your BindingSources.
parentBindingSource.DataSource = dSet;
parentBindingSource.DataMember = "ParentListDT";
childBindingSource.DataSource = parentBindingSource;
childBindingSource.DataMember = "ParentToChild";