Answered by:
N-tier passing dataset from DAL to BLL and BLL to DAL

Question
-
HI
i'm using an N-tier solution. WinForm and sql server DB
The DB ha just table with ine row
The following is the DAL code
Just a Sub to create a Dataset from DB and one Sub to update DB
Note that the DAL DAL Dataset is a Public Shared Property
Imports System.Data.SqlClient Imports Libreria Imports System.Windows.Forms Public Class DALAttivita ' DAL - DATA ACCESS LAYER Private Property QueryS As String Private Property Lastex As Exception Private Property DALAdapter As New SqlDataAdapter Public Shared Property DALDataset As New DataSet Public Sub SubGetAttivita() ' testa la connessione prima di iniziare QueryS = <sql> SELECT [AttivitaID] ,[RagioneSociale] ,[Indirizzo] FROM Tabelle.[Attivita] </sql>.Value Using CONN As New SqlConnection With {.ConnectionString = VG.FullCS} Using CMD As New SqlCommand With {.Connection = CONN, .CommandType = CommandType.Text, .CommandText = QueryS} ' crea il comando SELECT DALAdapter.SelectCommand = CMD Dim Builder As New SqlCommandBuilder(DALAdapter) DALAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey DALAdapter.TableMappings.Add("Table", "Attivita") Try CONN.Open() DALAdapter.Fill(DALDataset, "Attivita") DALAdapter.Dispose() CONN.Close() Catch ex As Exception MessageBox.Show("Errore lettura Achivio") Lastex = ex MessageBox.Show(ex.ToString) End Try End Using End Using End Sub Public Sub SubSaveAttivita() Using CONN As New SqlConnection With {.ConnectionString = VG.FullCS} Using CMD As New SqlCommand With {.Connection = CONN, .CommandType = CommandType.Text, .CommandText = QueryS} DALAdapter.SelectCommand = CMD Try CONN.Open() DALAdapter.Update(DALDataset.Tables("Attivita")) DALAdapter.Dispose() CONN.Close() Catch ex As Exception Lastex = ex MessageBox.Show("Errore salvataggio Achivio") MessageBox.Show(ex.ToString) End Try End Using End Using End Sub End Class
Now the following is the BLL code
' BLL Imports DataAccessLayer Public Class BLLAttivita Private Property DAL As New DALAttivita Private Property BLLAtt As ClasseAttivita Private Property BLLDataset As New DataSet Private Property BLLRow As DataRow Public Function FunGetAttivita() As ClasseAttivita ' BLLDataset = DAL.FunGetAttivita() 'prende il dataset come return DAL.SubGetAttivita() BLLDataset = DALAttivita.DALDataset For Each R As DataRow In BLLDataset.Tables("Attivita").Rows ' oppure cosi ? ' For Each R As DataRow In DALAttivita.DALDataset.Tables("Attivita").Rows BLLAtt = New ClasseAttivita With { .AttivitaID = R(0).ToString, .RagioneSociale = R(1), .Indirizzo = R(2) } Next Return BLLAtt End Function Public Sub SUBSaveAttivita(ByVal BLLAtt As ClasseAttivita) Dim BLLTable = BLLDataset.Tables("Attivita") BLLRow = BLLTable.Rows.Find(1) ' oppure cosi ? ' BLLRow = DALAttivita.DALDataset.Tables("Attivita").Rows.Find(1) BLLRow.BeginEdit() BLLRow("RagioneSociale") = BLLAtt.RagioneSociale BLLRow("Indirizzo") = BLLAtt.Indirizzo BLLRow.EndEdit() DAL.SubSaveAttivita() End Sub End Class
Note that in BLL afte calling DAL.SubGetAttivita() I copy DALDataset to BLLDataset
Then I apply the changes from UI to BLLDataset and call DAL.SubSaveAttivita() WITHOUT passing back to DAL the BLLDataset
EVERYTHING WORKS WHEN THE DB is updated
The question is, why the DAL can get the changes made in BLLDataset if it does not get back the BLLDataset ?
Saturday, January 6, 2018 12:08 PM
Answers
-
If, I'm following all of this correctly, then yes you should be able to simply refer to DALDataSet in DALAttivita.
I believe this statement is correct:
"By my thinking if BLLDataset is a reference to DALDataset, all changes made in BLLDATAset IN BLL class are changes to DALDataset in DAL - The fisical Dataset in memory is only ONE. "
As long as you are accessing a reference to a single instance of the DataSet, then all changes are reflected within that instance regardless of where you pass it off to.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
- Marked as answer by Claudio111 Saturday, January 6, 2018 4:27 PM
Saturday, January 6, 2018 3:59 PM
All replies
-
Are you calling DALAttivita.SubGetAttivita() after using the methods in BLLAttivita?
You are using different instances of DataSet in each class so the only way for the DAL to see any changes made in the BLL is for it to requery the data after the changes are made.
You might want to consider refactoring the code... get rid of the shared dataset member and explicitly pass a reference to a single dataset (which could still be a public member of the DAL). I suspect that the shared member is confusing you.
It might also be worth reviewing N-Tier development... you have the BLL creating an instance of the DAL and that's probably not a good idea. You should likely only have one instance of the DAL which other classes reference.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Saturday, January 6, 2018 1:28 PM -
May be i was not clear. The program work well. I thonl it should not work since I dont pass back dataset from BLL to DAL after i changed the table in BLLSaturday, January 6, 2018 1:48 PM
-
May be i was not clear. The program work well. I thonl it should not work since I dont pass back dataset from BLL to DAL after i changed the table in BLL
Sorry, I missed the line where you assign BLLDataset = DALAttivita.DALDataset after creating a new DataSet for BLLDataSet (no need for the new keyword in the declaration).
So it works because you're using the shared instance of the dataset.
As I suspected, it looks like that shared property is causing confusion for you.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Saturday, January 6, 2018 2:05 PM -
Hi reed
ok I forget Shared Property
Now the DALDataset is just Public. and it is passed to BLL in the FunGetAttivita
Maybe I have not understood one thing
If I call FunGetAttivita with this istruction
BLLDataset = DAL.FunGetAttivita()
do I get a copy of Dataset ( with other memry occupied) or BLLDataset has a just refences to DALDataset ?
Saturday, January 6, 2018 2:13 PM -
In the code you posted, that method returns an instance of ClasseAttivita not a dataset so that line of code would be invalid unless you've changed the method definition.
That said, the DataSet is a reference type so if you are returning the DataSet instance it is a reference to the instance not a copy of all of the data.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Saturday, January 6, 2018 2:20 PM -
so the following should be the right code
' BLL
'DAL Imports DatabaseOperation Imports System.Data.SqlClient Imports Libreria Imports System.Windows.Forms Public Class DALAttivita Private Property QueryS As String Private Property Lastex As Exception Private Property DALTable As DataTable Private Property DALDataset As New DataSet Private Property DALAdapter As New SqlDataAdapter Public Function FunGetAttivita() As DataSet ' testa prima la connessione ' ops.DBtestConnection() QueryS = <sql> SELECT [AttivitaID] ,[RagioneSociale] ,[Indirizzo] FROM Tabelle.[Attivita] </sql>.Value Using CONN As New SqlConnection With {.ConnectionString = VG.FullCS} Using CMD As New SqlCommand With {.Connection = CONN, .CommandType = CommandType.Text, .CommandText = QueryS} ' crea il comando SELECT DALAdapter.SelectCommand = CMD Dim Builder As New SqlCommandBuilder(DALAdapter) DALAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey DALAdapter.TableMappings.Add("Table", "Attivita") Try CONN.Open() DALAdapter.Fill(DALDataset, "Attivita") DALAdapter.Dispose() CONN.Close() Catch ex As Exception MessageBox.Show("Errore lettura Achivio") Lastex = ex MessageBox.Show(ex.ToString) End Try End Using End Using Return DALDataset End Function Public Function FunSaveAttivita(ByVal MioDatset As DataSet) As Boolean Using CONN As New SqlConnection With {.ConnectionString = VG.FullCS} Using CMD As New SqlCommand With {.Connection = CONN, .CommandType = CommandType.Text, .CommandText = QueryS} DALAdapter.SelectCommand = CMD Try CONN.Open() DALAdapter.Update(DALDataset.Tables("Attivita")) CONN.Close() Catch ex As Exception Lastex = ex MessageBox.Show("Errore salvataggio Achivio") MessageBox.Show(ex.ToString) End Try End Using End Using Return True ' to be changed with exception...to do End Function End Class
Imports DataAccessLayer Public Class BLLAttivita Private Property DAL As New DALAttivita Private Property BLLAtt As ClasseAttivita Private Property BLLDataset As DataSet Private Property BLLRow As DataRow Public Function FunGetAttivita() As ClasseAttivita BLLDataset = DAL.FunGetAttivita() 'prende il dataset For Each R As DataRow In BLLDataset.Tables("Attivita").Rows BLLAtt = New ClasseAttivita With { .AttivitaID = R(0).ToString, .RagioneSociale = R(1), .Indirizzo = R(2) } Next Return BLLAtt End Function Public Function FunSaveAttivita(ByVal BLLAtt As ClasseAttivita) As Boolean Dim BLLTable = BLLDataset.Tables("Attivita") BLLRow = BLLTable.Rows.Find(1) BLLRow.BeginEdit() ' la chiave primaria non puo' essere modifica ' BLLRow(0) = BLLAtt.AttivitaID BLLRow("RagioneSociale") = BLLAtt.RagioneSociale BLLRow("Indirizzo") = BLLAtt.Indirizzo BLLRow.EndEdit() DAL.FunSaveAttivita(BLLDataset) Return True End Function End Class
If it is the right code why DALDataset should be Public - It seems it can be PrivateSaturday, January 6, 2018 2:39 PM -
Now that you are passing the reference via a method call, you are correct that the underlying variable can be private. It only needed to be public if you were going to access it from the DLL instance as a property member.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
- Marked as answer by Claudio111 Saturday, January 6, 2018 3:05 PM
- Unmarked as answer by Claudio111 Saturday, January 6, 2018 3:08 PM
Saturday, January 6, 2018 2:45 PM -
Last Question (I hope)
In the last code posted it is true that I can call
DAL.FunSaveAttivita(BLLDataset)
even in this way
DAL.DAL.FunSaveAttivita() ...i mean without pass BLLDataset ?
(Of course modifing also the method in DAL)
By my thinking if BLLDataset is a reference to DALDataset, all changes made in BLLDATAset IN BLL class are changes to DALDataset in DAL - The fisical Dataset in memory is only ONE.
It is Right ?
Saturday, January 6, 2018 3:16 PM -
If, I'm following all of this correctly, then yes you should be able to simply refer to DALDataSet in DALAttivita.
I believe this statement is correct:
"By my thinking if BLLDataset is a reference to DALDataset, all changes made in BLLDATAset IN BLL class are changes to DALDataset in DAL - The fisical Dataset in memory is only ONE. "
As long as you are accessing a reference to a single instance of the DataSet, then all changes are reflected within that instance regardless of where you pass it off to.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
- Marked as answer by Claudio111 Saturday, January 6, 2018 4:27 PM
Saturday, January 6, 2018 3:59 PM -
Pk. Thank you very much. Everything is clear now.Saturday, January 6, 2018 4:27 PM
-
Pk. Thank you very much. Everything is clear now.
Well understand the difference between Layered and n-tier.
https://msdn.microsoft.com/en-us/library/ee658117.aspx
Find out about other patterns....
https://msdn.microsoft.com/en-us/library/ff649690.aspx
https://www.codeproject.com/Reference/731015/The-repository-pattern-in-VB-Net
http://blog.sapiensworks.com/post/2012/11/01/Repository-vs-DAO.aspx
DAO pattern can be used with .NET languages such a C# and VB.NET
https://en.wikipedia.org/wiki/Data_access_object
You may want to get it and learn more of what is happening in architecting .NET solutions.
You get all the source code, you can run it all in debug mode and see what is happening.
http://www.dofactory.com/products/net-design-pattern-framework
http://lauteikkehn.blogspot.com/2012/03/datatable-vs-list.html
https://dzone.com/articles/reasons-move-datatables
Sunday, January 7, 2018 11:47 AM