How connect adapter from view to model in MVP - c#

Am not shure how to do this. Am litle confused, in my project c# winforms am using MVP pattern for deskotp application.
I have datagridview where i show products gorup. Database query for selecting products group is stored in model and that method for selecting return DataTable. Next, presenter call that model function for selecting and pass it to view. In view i put that DataTable in BindingSource and in gridview as DataSource i pass binding source.
This work good but what when i try to add new row in grid and try to save that new row?
What if i want to edit existing row and update that record to database.
If i want to create/update record from database i need to access to adapter and call update. Problem is becouse my adapter is in model not in view.
Am not shure how to from view access to adapter and dataset to model.
Check my code for selecting:
Model:
public DataTable SelectAll()
{
using (MySqlConnection conn = new MySqlConnection(Properties.Settings.Default.ConnectionString))
{
try
{
conn.Open();
string query = "SELECT Naziv, Opis FROM grupe";
using (MySqlDataAdapter adapter = new MySqlDataAdapter(query, conn))
{
dt = new DataTable();
ds = new DataSet();
adapter.Fill(ds, "grupe");
dt = ds.Tables["grupe"];
}
conn.Close();
}
catch(MySqlException ex)
{
MessageBox.Show(ex.Message);
}
}
return dt;
}
Presenter:
public DataTable SelectAll()
{
return _model.SelectAll();
}
View:
private void GrupeArtikala_Load(object sender, EventArgs e)
{
bs = new BindingSource();
bs.DataSource = _presenter.SelectAll();
groupDataGridView.DataSource = bs;
}
So now when i want to save changes to database i need to access to model database adapter but i dont know how.
private void saveToolStripButton_Click(object sender, EventArgs e)
{
changes = ds.GetChanges(); // DatSet changes is in model but i must access here but dont know how
if (changes != null)
{
int updatedRows = dataAdapter.Update(changes); // Adapter is in model and i need him here
ds.AcceptChanges();
}
}
Am not shure how to connect this to model to avoid mixing database queries in view forms.
Anyone can give me example to do this.

If I understand correctly, you need to call functions on objects belonging to your model, but you don't want your view to have a reference to your model. Is that right? If so, you could follow the pattern you used with the SelectAll function:
bs.DataSource = _presenter.SelectAll();
You are calling _presenter.SelectAll in the view, but ultimately getting the returned value from the model. So to call ds.GetChanges in your view, you could add a GetDataSetChanges function to your presenter:
public DataSet GetDataSetChanges()
{
return _model.GetDataSetChanges();
}
Same thing for calling update on your adapter. Add a function to the presenter:
public int UpdateAdapter(DataSet dataSet)
{
return _model.UpdateAdapter(dataSet);
}

Related

SQLite Data Adapter not displaying data

I'm trying to fill a data grid view in my windows form application but nothing is being returned from the database when I execute the select query. I've looked at other questions about this topic on this site but cannot find anything that addresses my problem.
The name of the data view table is qbcMemDataView and the data source is a sqlite dataset called sqlite_dbDataSet1
Here is the code I have in place:
public Form1()
{
InitializeComponent();
dbConnection = new SQLiteConnection("Data Source=sqlite_db.sqlite;Version=3");
dbConnection.Open();
string[] restrictions = new string[4];
restrictions[2] = "test_table_mom";
using (DataTable dTbl = dbConnection.GetSchema("Tables", restrictions))
{
for (int i = 0; i < dTbl.Rows.Count; i++)
{
tblChooser.Items.Add(dTbl.Rows[i].ItemArray[dTbl.Columns.IndexOf("TABLE_NAME")].ToString());
}
if (tblChooser.Items.Count > 0)
{
tblChooser.SelectedIndex = 0;
}
}
}
private void btnSelect_tbl_Click(object sender, EventArgs e)
{
string sql = "SELECT id, name FROM test_table_mom";
using (SQLiteDataAdapter dbAdapter = new SQLiteDataAdapter(sql, dbConnection))
{
DataTable dataTbl = new DataTable();
dbAdapter.Fill(dataTbl);
qbcMemDataView.DataSource = dataTbl;
}
}
Also, here is a screenshot of the program running that might help better explain the issue I am having: http://imgur.com/j9ffeVi
I know there is data inside the table, I just don't know why it is not appearing in the data grid when the btnSelect_tbl_Click method is executed.
Any help would be appreciated.
Thanks!
Per the tutorial How to: Bind Data to the Windows Forms DataGridView Control, you are missing a BindingSource component that binds the data from the datasource to your table to the DataGrid.
Initialize the BindingSource at the top of your class like so:
private BindingSource bindingSource1 = new BindingSource();
Then near the top of your button click method before the sql add the line:
qbcMemDataView.DataSource = bindingSource1;
and finally change the last line of code
qbcMemDataView.DataSource = dataTbl;
to
bindingSource1.DataSource = dataTbl;
try that and see if it works for you.
Note: I'm not sure if this applies to c# but maybe it's universal fix.
Android builtin adapters and such use _id as the name of the id field. The other problem is _id and id well it's not well documented in android.
About "_id" field in Android SQLite
You can use this technique renaming in the select but it gets messy and you may not catch all occurrences.
string sql = "SELECT id _id, name FROM test_table_mom";
My Opinion: Go back and refactor your db id to _id.

WPF C# - Loading MySQL Query into DataGrid

I am attempting to build a simple application that allows me to interact with a MySQL database I have set up. I can add records just fine; however, I cannot get them to display. I am simply presented with a blank datagrid control.
It could be something simple, but I have tried different approaches, searched online, and messed with it longer than I should have - to no avail. I have a feeling the issue might lie in my lack of understanding the DataGrid control. Any help is sincerely appreciated.
The Select method from the Database Connection class:
public DataTable Select(string tableName)
{
string query = "SELECT * FROM " + tableName;
this.Open();
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
DataSet dataSet = new DataSet();
adapter.Fill(dataSet);
this.Close();
return dataSet.Tables[0];
}
The following is a portion of the code for the window (called View) containing the datagrid. The table name is passed to it from the main window upon the click of a button.
public View()
{
InitializeComponent();
}
public View(string table)
{
this.table = table;
InitializeComponent();
}
private void windowLoad(object sender, RoutedEventArgs e)
{
DatabaseConnection myConnection = new DatabaseConnection();
dataGrid.DataContext = myConnection.Select(table).DefaultView;
}

Refresh BindingSource correctly

I have a master-detail grid view on windows forms. I a very simple Repository (repo in code) that queries the database to get back DataTables.
At first I load the Data and define a relation like u see in the LoadData() method. Next, After I edit my Master table I want to refresh the view datasource. That's the unimplemented RefreshData(); method. If I'm refreshing after Edit I need the bindingsource not to lose the "current" row.
Here is the code:
public void LoadData()
{
//define the Bindingsource and 2 Datatables.
binder = new BindingSource();
tbTaxPayers = repo.GetTaxPayersDataTable(-1);
tbLinkedOrganizations = repo.GetTaxPayersLinkedOrganizations();
//create a dataset to define the relation so that the view can pick it up
ds = new DataSet();
ds.Tables.Add(tbTaxPayers);
ds.Tables.Add(tbLinkedOrganizations);
ds.Relations.Add("LinkedOrganizations", tbTaxPayers.Columns["CLI_ID"], tbLinkedOrganizations.Columns["LCC_CLI_ID_PARENT"]);
//set datasource to the main table.
binder.DataSource = tbTaxPayers;
view.LoadData(binder);
}
public void RefreshData()
{
// how to refresh without overhead ? and without losing focus if I just edit ?
}
EDIT:
By doing the next code it works but I have to create a new DataSet with every refresh. And it smells to me cause it almost a duplicate of my LoadData() method.
public void RefreshData()
{
tbTaxPayers = repo.GetTaxPayersDataTable(-1);
tbLinkedOrganizations = repo.GetTaxPayersLinkedOrganizations();
ds = new DataSet();
ds.Tables.Add(tbTaxPayers);
ds.Tables.Add(tbLinkedOrganizations);
ds.Relations.Add("LinkedOrganizations", tbTaxPayers.Columns["CLI_ID"], tbLinkedOrganizations.Columns["LCC_CLI_ID_PARENT"]);
binder.DataSource = tbTaxPayers;
}

Populate GridView with resultset of stored procedure

I've been struggling with displaying the resultset of a stored procedure in a grid view on the click of a button.
My issue is that am working on the existing code of a portal based on 3-tier architecture which doesn't allow me to use stuff like SqlDataAdapter and such. Because such functionality have already been incorporated by some methods which are available in the form of dlls.
I've tried returning a DataTable or a DataSet as the data source of the gridview but in vain.
Please help me by suggesting if there is any alternative object that can be assigned to the datasource of the gridview.. I am new to all this.. Any help is most appreciated !!
Here is my code:
DataAccess Layer:
public IDataReader BindGridView(string rgn)
{
string spdName = "spd_get_default_region";
DbCommand cmd = DB.GetStoredProcCommand(spdName);
DB.AddInParameter(cmd, "Rgn", DbType.String, rgn);
IDataReader idr = cmd.ExecuteReader();
return idr;
}
Here, GetStoredProcCommand is a built-in method. gvAll is the ID of the gridview.
Grid.aspx.cs:
protected void Go_Rgn_Click(object sender, EventArgs e)
{
DAL da=new DAL();
plhTable.Visible = true;
plhChoose.Visible = false;
plhForm.Visible = false;
string Rgn = afRgn.Text;
gvAll.DataSource = da.BindGridView(Rgn);
gvAll.DataBind();
}
A simple alternative is to create a dataTable object.
DataTable defaultRegion = new DataTable();
defaultRegion.Load(cmd.ExecuteReader());
gvAll.DataSource = table;
gvAll.DataBind();

Databound DataGridView Empty Despite Full DataSource

I have a base form class that contains a method that returns a DataTable:
protected DataTable GetTableData(string sql, OracleConnection connection)
{
DataTable table = null;
OracleDataAdapter adapter = null;
try
{
table = new DataTable();
adapter = new OracleDataAdapter(sql, connection);
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
adapter.Fill(table);
}
catch (Exception e)
{
MessageBox.Show("An error occurred while trying to process your request:\n\n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (null != adapter)
{
adapter.Dispose();
}
}
return table;
}
Another window is a subclass of it, and invokes it as follows:
private void LoadViewData(OracleConnection connection)
{
DataTable table = null;
try
{
var sql = "SELECT * FROM " + this.ObjectName;
table = GetTableData(sql, connection);
this.resultBindingSource.DataSource = table;
}
catch (Exception e)
{
MessageBox.Show("An error occurred while trying to process your request:\n\n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
this.sqlEditor.Focus();
}
}
resultBindingSource is a System.Windows.Forms.BindingSource. It is set as the DataSource property of a System.Windows.Forms.DataGridView. (The expression, this.ObjectName, evaluates to the name of a table or view in the database.)
When I run through the code in the debugger, I can see that the SQL executes just fine. I can see that the DataTable contains data. I can see that the DataGridView control is properly bound to the data source, and that I can see the data in the data table through its DataSource property. However, no data is displayed in the control itself. There are no row or column headers, and no data is displayed whatsoever.
I have tried everything I can think of to pin down the cause of this problem. This code works exactly as shown on another form. I tried deleting the controls in question and recreating them, to no avail. I consulted the articles on MSDN on how to properly databind to a DataGridView control. I tried it with and without an OracleCommandBuilder (which doesn't seem necessary to me, since this is a read-only view of the data).
I'm frankly out of ideas. It's likely something fairly obvious that I've overlooked. I know that databinding works, because I've done it before with great success.
Any pointers in the right direction would be greatly appreciated.
I tried recreating your program using the pieces you mentioned here. I didn't actually get data from a datatable but that's irrelevant. Here's what I did:
public partial class Form1 : BaseForm
{
BindingSource source = new BindingSource();
public Form1()
{
InitializeComponent();
this.dataGridView1.DataSource = source;
}
private void button1_Click(object sender, EventArgs e)
{
DataTable table = GetDataTable();
this.source.DataSource = table;
}
}
public class BaseForm : Form
{
protected DataTable GetDataTable()
{
DataTable result = new DataTable();
result.Columns.Add("Name");
result.Columns.Add("Age", typeof(int));
result.Rows.Add("Alex", 27);
return result;
}
}
Is this roughly the same thing you have? I had no issues at all. Based on what you're posting this SHOULD work. Are you sure you're binding everything to each other correctly? Post more of your binding code if possible...

Categories