entity framework adding data it shouldnt through other object - mysql

I think this question has been asked already, i just can't seem to find an answer i understand.
I have a program that works with entity framework - code first.
When the program runs and the database is not created yet, it will create it and add some data to it as well.
The data it adds are 3 categories, each customer will get a category assigned when a object of customer is created.
The 3 categories are also databound to a combobox, when a customer is created, the categorie is selected from the combobox
problem: when a customer is created, a copy of the category seems to be created as well, the category copy is added to the table of categories (not suppose to happen in my head) and then of course this copy is also added to the combobox.
I'm having trouble understanding why this is happening and what i did wrong.
I'm also not sure which parts of the code i should post here or where i should be looking for error, although i have a feeling the situation result from a bad database design/class design.
This is my first time working with entity framework
Code for the databindings
Dim DisplayLimos As New BindingSource
context.LimosDb.Load()
DisplayLimos.DataSource = context.LimosDb.Local.ToBindingList()
CbLimos.DataSource = DisplayLimos
CbLimos.DisplayMember = "Info"
Dim DisplayCategories As New BindingSource
context.CategoriesDb.Load()
DisplayCategories.DataSource = context.CategoriesDb.Local.ToBindingList()
CbCategorie.DataSource = DisplayCategories
CbCategorie.DisplayMember = "Naam"
Dim DisplayKlanten As New BindingSource
context.KlantenDb.Load()
DisplayKlanten.DataSource = context.KlantenDb.Local.ToBindingList()
ListBoxKlanten.DataSource = DisplayKlanten
ListBoxKlanten.DisplayMember = "Naam"
Dim displayArrangementen As New BindingSource
context.ArrangementenDb.Load()
displayArrangementen.DataSource = context.ArrangementenDb.Local.ToBindingList()
CbArrangementen.DataSource = displayArrangementen
CbArrangementen.DisplayMember = "Naam"
Code for populating the categories table the second parameter is a class that holds discounts for each category
Dim categorieVip As New KlantenCategorie("Vip", kortingVip)
Dim categorieWedding As New KlantenCategorie("Wedding", kortingWeddingPlanner)
Dim categorieNightLife As New KlantenCategorie("NightLife", kortingConcertenPlanner)
context.CategoriesDb.Add(categorieVip)
context.CategoriesDb.Add(categorieWedding)
context.CategoriesDb.Add(categorieNightLife)
context.SaveChanges()
Code that adds the customer to the database and where the error occurs that a copy of the category is also created
Private Sub BtnKlant_Click(sender As Object, e As EventArgs) Handles BtnKlant.Click
Dim adres As New Adres(TxbStraat.Text, TxbHuisN.Text, CType(TxbPostCode.Text, Integer), TxbGemeente.Text)
Dim klant As New Klant(CType(TxbKlantNr.Text, Integer), TxbVoorNaam.Text, TxbNaam.Text, adres, CType(TxbBtwNr.Text, Integer), CType(CbCategorie.SelectedValue, KlantenCategorie))
Try
_Context.KlantenDb.Add(klant)
_Context.SaveChanges()
ListBoxKlanten.Refresh()
MessageBox.Show("Klant succesvol toegevoegt")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub

I believe i have found where my mistake lies.
In the part where i create a new customer and pass through the category it should have
Private Sub BtnKlant_Click(sender As Object, e As EventArgs) Handles BtnKlant.Click
Dim adres As New Adres(TxbStraat.Text, TxbHuisN.Text, CType(TxbPostCode.Text, Integer), TxbGemeente.Text)
Dim klant As New Klant(CType(TxbKlantNr.Text, Integer), TxbVoorNaam.Text, TxbNaam.Text, adres, CType(TxbBtwNr.Text, Integer), CType(CbCategorie.SelectedValue, KlantenCategorie))
Try
_Context.KlantenDb.Add(klant)
_Context.SaveChanges()
ListBoxKlanten.Refresh()
MessageBox.Show("Klant succesvol toegevoegt")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
I changed this
Dim klant As New Klant(CType(TxbKlantNr.Text, Integer), TxbVoorNaam.Text, TxbNaam.Text, adres, CType(TxbBtwNr.Text, Integer), CType(CbCategorie.SelectedValue, KlantenCategorie))
to this
Dim klant As New Klant(CType(TxbKlantNr.Text, Integer), TxbVoorNaam.Text, TxbNaam.Text, adres, CType(TxbBtwNr.Text, Integer), _Context.CategoriesDb.First(Function(ct) ct.Naam = CbCategorie.Text))
Using a lambda to pull the correct category out of the database and link it to the new customer created. (atleast that is how i understand it)
This link is what i am mostly going on to create this project, one of the few i found on code first EF with actual VB examples.
http://visualstudiomagazine.com/articles/2012/03/07/an-ef-code-first-tutorial.aspx
If anyone wants to add criticism to my way of working or coding, please do!
I am always open to improving my nooby skills :)

Related

tableadapter not deleting programatically removed datatable rows

I have a dataset linked with a MYSQL database via tableadpators and a TableAdpaterManager (all autographed through designer view). The visual studio route was setting up a DataSource and then dragging individual tables onto the form.
Now, I can update, insert and delete records in the database if I edit the datagridviews manually. However, if I remove datarows programatically, the rows are not deleted in the database.
The removal code:
Public Shared Sub RemoveDuplicateRowsViaField(dt As DataTable, RowName As String)
Dim rowList As New List(Of String)
Dim dr As DataRow
For i = dt.Rows.Count - 1 To 0 Step -1
dr = dt(i)
If rowList.Contains(dr.Item(RowName)) Then
dt.Rows.Remove(dr)
Else
rowList.Add(dr.Item(RowName))
End If
Next
dt.DataSet.AcceptChanges()
End Sub
And the 'save' code:
Private Sub SaveOrganisationsBT_Click(sender As Object, e As EventArgs) Handles SaveOrganisationsBT.Click
Me.Validate()
Me.Gi_usersBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.dbDS)
End Sub
I've tried many things including looking into the tableAdapters in dataset design view, but am at a loss. Can anyone help?
Nevermind. Solved it. It appears to be around the use of AcceptChanges on the datasource. The code below works. I've read that datarow.remove both deletes the row and accepts changes. I'm guessing if changes are accepted then the tableadapter can't discern it needs deleting from its non 'dirty' state, given changes have been accepted, thus clearing the status of the row? Just supposition. The working code:
Public Shared Sub RemoveDuplicateRowsViaField(dt As DataTable, RowName As String)
Dim rowList As New List(Of String)
Dim dr As DataRow
For i = dt.Rows.Count - 1 To 0 Step -1
dr = dt(i)
If rowList.Contains(dr.Item(RowName)) Then
dr.Delete()
Else
rowList.Add(dr.Item(RowName))
End If
Next
End Sub

DIsplay real time SQL data on web form

I am working on a small project but currently stuck in the process and your help would be much appreciated.
I am trying to display data from one of my SQL tables onto web form (asp), which will effectively be updating as long as data is being entered into the table.
I have managed to get it to work by using the META Tag which refreshes the page every 2 seconds, but I know this is not an ideal way of doing it. It was advised to me to update the web form only from server to client when there is a new inserted value, however I do not know how to approach this.
Please see below to my current code.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Label1.Text = "Cache Refresh:" & _
Date.Now.ToLongTimeString
SqlDependency.Start(GetConnectionSTring())
Using connection As New SqlConnection(GetConnectionSTring())
Using Command As New SqlCommand(GetSQL(), connection)
Dim Dependency As New SqlCacheDependency(Command)
Dim NumberOfMinutes As Integer = 3
Dim Expires As Date = _
DateTime.Now.AddMinutes(NumberOfMinutes)
Response.Cache.SetExpires(Expires)
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(True)
Response.AddCacheDependency(Dependency)
connection.Open()
GridView1.DataSource = Command.ExecuteReader()
GridView1.DataBind()
End Using
End Using
End Sub
Private Function GetConnectionSTring() As String
Return "Data Source=xxxxxxxxx; Initial Catalog=Test; User ID=xxx; Password= xxx;"
End Function
Private Function GetSQL() As String
Return "SELECT ProductCode, ProductName, Cost FROM dbo.OrderTempTable"
End Function
Thank you for your input.
I think you have to check the DB every certain time.
THIS is for PHP but the idea is the same.
HERE another example.

Copy GridView data to table in database

I have data in a GridView and I need to copy it to a table in a database.
Let's say my first GridView is GridView1; GridView1's database source is subjects_enrolled. After I'm done using GridView1 it's data needs to clear and in addition, clear the data in the source table.
Note: The primary purpose of GridView1 is for displaying data for printing a page, but I want to save or transfer all data in GridView1 to a database table before losing the GridView1 data.
Here is my code so far:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Me.IsPostBack Then
Dim constr As String = ConfigurationManager.ConnectionStrings("mcbdatabseConnectionString").ConnectionString
Using con As New MySqlConnection(constr)
Using cmd As New MySqlCommand("SELECT Subject_ID, Subject, Units FROM mcbdatabse.subject_enrolled")
Using sda As New MySqlDataAdapter()
cmd.Connection = con
sda.SelectCommand = cmd
Using dt As New DataTable()
sda.Fill(dt)
GridView1.DataSource = dt
GridView1.DataBind()
End Using
End Using
End Using
End Using
End If
txtDate.Text = Date.Today.ToString("yyyy-MM-dd")
End Sub
When you doing some unnormal activity about databases you can be sure that you are in a bad plan. So in your case i can not understand why you want to do this.
You have better ways to do this, you can put all data in one table and add a column named 'enrolld' to filter data as you want and on user click you can delete or enrol the record.
But if you want to continue this way, you we have some events in gridview that can help:
RowDeleting, RowUpdating
If a row affected the related event fires and you can get the id of the record:
protected sub GridView1_RowDeleting(byval sender as object, byval e as GridViewDeleteEventArgs)
{
dim a as object = e.Keys["Id"]
'or
dim a as object = e.Keys[0]
}
To access the id of your record and do what you want with this.

Populating text boxes via Combobox and SQL database table

I am trying to populate a set of textboxes from a combobox on a form. The combo box is populated using a dataset when the form loads. When this is loaded it needs to show only one entry per unit number in the kitcombobox (which is a unit number for a kit with multiple pieces of equipment in it) but display the multiple pieces of equipment's information in the different text boxes when the unit number is selected via the kitcombobox. What approach should I take towards this? I'm really lost and this is all I have so far :(
Private Sub ckunit()
Dim ds As New DataSet
Dim cs As String = My.Settings.MacroQualityConnectionString
Dim kitcombobox As String = "SELECT DISTINCT Unit_Number, Status FROM Calibrated_Equipment WHERE CHARINDEX('CK', Unit_Number) > 0 AND Status='" & ckstatuscombbx.Text & "'"
Dim sqlconnect As New SqlConnection(cs)
Dim da As New SqlDataAdapter(kitcombobox, sqlconnect)
sqlconnect.Open()
da.Fill(ds, "Calibrated_Equipment")
sqlconnect.Close()
kitcombbx.DataSource = ds.Tables(0)
End Sub
Assuming you are using WinForms, I think the key will be adding an event handler for the SelectionChangedCommitted event on kitcombbx.
You can then checked the properties on the combobox to check what is selected and run another query to pull equipment information for that kit. It'd probably look something like this:
Private Sub kitcombbx_SelectionChangeCommitted(sender As Object, e As EventArgs) _
Handles kitcombbx.SelectionChangeCommitted
Dim kit = kitcombbx.SelectedItem.ToString()
Dim kitEquipment = FetchKitEquipmentInformation(kit)
PopulateEquipmentInformation(kitEquipment)
End Sub
The way you're currently constructing your query (by concatenating string parameters directly from user input) results in bad performance for most database systems, and moreover, is a huge security vulnerability. Look up SQL injection for more detail (or read these two questions).
Better DB code would probably look something like this:
Dim query = New StringBuilder()
query.AppendLine("SELECT DISTINCT Unit_Number, Status ")
query.AppendLine("FROM Calibrated_Equipment ")
query.AppendLine("WHERE CHARINDEX('CK', Unit_Number) > 0 ")
query.AppendLine(" AND Status = #STATUS ")
Dim connection As New SqlConnection(My.Settings.MacroQualityConnectionString)
Dim command As New SqlCommand(query, connection);
command.Parameters.Add("#STATUS", ckstatuscombbx.Text);
Dim da As New SqlDataAdapter(kitcombobox, sqlconnect)
'And so on...
Your question is a bit broad (and therefore, likely off-topic for StackOverflow), see How to Ask.

Populate a textbox with mysql data after a combobox selection

So I have 2 mysql tables, one called "Service_Details" and one called "Payment_details"
I have a combobox in my form which displays the "service_id" field from the service table.
I'm trying to code a textbox, so when I select the service id from the combobox it writes the "service" which is another field in my service details table. The service id is linked to a service.
I am getting errors 'identifier expected' at [0] and 'Value of type 'system.data.datatablecollection' cannot be converted to 'string' at dss.tables
I can't seem to get it working after browsing the internet for an hour
Here is my code:
Private Sub cbxserviceid_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbxserviceid.SelectedIndexChanged
Dim dss As New DataSet
Dim daa As New MySqlDataAdapter("SELECT * from service_details WHERE ServiceID='" + cbxserviceid.Text + "'", objconnection)
Dim cmddd = New MySqlCommandBuilder(daa)
daa.Fill(dss)
txtService1.Text = dss.Tables[0].Rows[0]["Service"].ToString();
End Sub
The indexes in VB.NET are expressed using the round braces, the square brackets are used in C#
txtService1.Text = dss.Tables(0).Rows(0)("Service").ToString()
Also avoid to use string concatenation for sql command texts, use always a parameterized query
Private Sub cbxserviceid_SelectedIndexChanged(......)
Dim dss As New DataSet
if cbxserviceid.SelectedIndex <> -1 Then
Dim daa As New MySqlDataAdapter("SELECT * from service_details WHERE ServiceID=#id", _
objconnection)
daa.SelectCommand.Parameters.AddWithValue("#id", Convert.ToInt32(cbxserviceid.Text))
daa.Fill(dss)
txtService1.Text = dss.Tables(0).Rows(0)("Service").ToString()
End If
End Sub
I have also removed the creation of the MySqlCommandBuilder, being the adapter a local variable it has no sense or effect (if this is all your code in this event of course).
Looking at the comments below and the chat with the poster there is also another error to fix.
When assign a DataSource, DisplayMember and ValueMember property of a combobox it is mandatory to follow a precise order to avoid unwanted side effects
cbxserviceid.DisplayMember = "ServiceID"
cbxserviceid.ValueMember = "ServiceID"
cbxserviceid.DataSource = datatable