I have a Two identical data tables in my project, One is Purchase Orders and the other is a template datatable. (IE: the user can select a template when creating a new row in the original table.)
A Save Template button runs:
Public Shared Sub AddPO_as_Template(Name As String, DR As DataRow)
Dim ds As New SomeDataSet
Dim ta As New SomeDataSetDataSetTableAdapters.PurchaseOrderTemplatesTableAdapter
Try
DR("Name") = Name
ds.PurchaseOrderTemplates.ImportRow(DR)
ta.Update(ds)
Catch ex As Exception
CommonRoutines.ShowExceptionDialog("Could not add the Template, an error occured.", ex.Message)
End Try
End Sub
This particular code throws a concurrency violation. I assume this is happening because the ID column is auto increment and I as using the origional row's ID.
Now; the ID in the second table (PurchaseOrderTemplates) is not important at all, so it can be anything. I have tried setting -1, dbnull, "", etc.... the DB keeps trowing exceptions on the update command.
How can I reset the ID column so it just adds as normal? (I know i could create a newrow and move all the columns accross, but this seems the long way.)
Thanks
EDIT: Copying the rows (via .itemarray) works fine, but i need to get the auto increment value from the table somehow to avoid concurrency violations.
Edit2: So i got it working as per the answer below, but I'd still love to know how to get import row working like this.
Adding the Row as follows works.
Public Shared Sub AddPO_as_Template(Name As String, DR As DataRow)
Dim ds As New SomeDataSet
Dim ta As New SomeDataSetTableAdapters.PurchaseOrderTemplatesTableAdapter
Dim NewRow As DataRow
NewRow = ds.PurchaseOrderTemplates.NewRow
NewRow.ItemArray = DR.ItemArray
NewRow("Name") = Name
NewRow("ID") = 1
ds.PurchaseOrderTemplates.Rows.Add(NewRow)
ta.Update(ds)
End Sub
The MySQL database ignores the value in the ID column, and just sets its own auto increment value.
Related
Might be a bad title but as a non-english speaking person not everything is simple.
My problem is the following:
Fetching data from Mysql database (No problem)
Adding a Combobox in my Datagridview (No problem)
Inserting the result into that combobox (Problem)
What happens is that the combobox shows me the number of results, it is showing me 212 as a single possibility to click and not the value of the MySQL cell.
My code looks like this:
'//Henter drivere fra Printer Installer Database //'
mysqlconnpi.Open()
query = "Select model_name from printer_installer.ppp_drivers"
data = New DataTable
dataAdap = New Devart.Data.MySql.MySqlDataAdapter(query, mysqlconnpi)
Dim cmb As New DataGridViewComboBoxColumn()
cmb.HeaderText = "Select Data"
cmb.Name = "cmb"
cmb.MaxDropDownItems = 100
cmb.Items.Add(dataAdap.Fill(data))
DataGridView1.Columns.Add(cmb)
The result is this:
What is wrong with my code?
Also, I found out that the combobox only could handle 100 items, is there a way for my to get more? I currently have 212 drivers in the database I want to list.
EDIT:
I testet to add this line:
DataGridView1.DataSource = data
to the code just to check if "data" even had items.
the result is this:
Not allowed to insert embedded, image is here.
The code is now:
'//Henter drivere fra Printer Installer Database //'
mysqlconnpi.Open()
query = "Select model_name from printer_installer.ppp_drivers"
data = New DataTable
dataAdap = New Devart.Data.MySql.MySqlDataAdapter(query, mysqlconnpi)
Dim cmb As New DataGridViewComboBoxColumn()
cmb.HeaderText = "driver"
cmb.Name = "cmb"
cmb.MaxDropDownItems = 100
cmb.Items.Add(dataAdap.Fill(data))
DataGridView1.Columns.Add(cmb)
DataGridView1.DataSource = data
'DataGridView1.DataSource = dataAdap.Fill(data)
'-------------------------------------------------'
The DataGridView might be looking at the string length which is the property of string the result of the query so you might want to send the result by wrapping your string. You can use linq in place of your sql query.
From model in printer_installer.ppp_drivers select new with {Key .name =model.model_name}
I'm new in MS Access. Currently i need to create a serial number, an autonumber pair with a sub-autonumber. Something like M1-1,M1-2,M1-3,... M2-1,M2-2,M2-3,... M3-1,M3-2,... The number must be unique.
I created a table for Main running number for M1,M2,M3,... create an index to make it unique. Then another table for sub-number, 1,2,3,4,... after that a MainNum foreign key (relationship) and another Index to make it unique.
But the problem is second table i cant figure out a way to make it an autonumber/running number, because it may repeat itself.
Currently out of idea, need some help.
I'd recommend to do not use the serial number as primary/foreign key in tables. Use numeric fields for this: autonumber for primary and number for foreign. It works faster and automatically.
For generating serial number create public function, which can return next value or optionally current one depending on arguments. Current values of first and second part of serial number store in table, lock it when generating new number, it will guarantee unique next number even in multiuser environment. Also you may store all generated numbers in table with composite unique index on both numbers.
Make your PK an autonumber and use that for any relationships. For your serial number use two long integer fields (SN1, SN2). In the before_update event of your form, for new records, call a public function to generate new 'serial numbers'.
Private Sub Form_BeforeUpdate(Cancel As Integer)
Dim lngSN1 AS Long
Dim lngSN2 as Long
If Me.NewRecord Then
'if SN1 is not to be incremented, set it here to whatever you want
If GetSerials(SN1, SN2) Then
Me!SN1 = lngSN1
Me!SN2 = lngSN2
Else
Cancel = True
End If
End If
End Sub
Public Function GetSerials(ByRef SN1 as Long, ByRef SN2 as Long) AS Boolean
If SN1 = 0 Then
SN1 = Nz(DMax("SN1","<yourTable>"), 0) + 1
SN2 = 1
Else
SN2 = DMax("SN2", "<yourtable>","SN1=" & SN1) + 1
End IF
GetSerials = True
End Function
Build a query with a calculated field to create your composite 'SerialNumber'.
SELECT *, "M" & SN1 & "-" & SN2 as SerialNumber FROM <yourtable>
Use that query wherever you want to display the SerialNumber.
I need to check a mysql table periodically and if there are any rows found, I need to loop through them and perform some actions.
My SQL string is nice and simple: "SELECT * FROM 'dbcpman_jobs'".
There could be 1 returned row, or there could be 20 returned rows.
For each returned row, I need to assign some of the data to variables...
Dim job_id As String = jobrow.Item("id")
Dim job_jobid As String = jobrow.Item("jobid")
Dim job_status As String = jobrow.Item("status")
Dim job_dbxid As String = jobrow.Item("dbxid")
Then i need to make an API call using the information that's just been split out...
Try
Dim jobapicall As New System.Net.WebClient
jobcheckresult = jobapicall.DownloadString(fulljobapicheckurl)
Catch ex As Exception
Console.WriteLine("Error 'DBX-Err-1' - Error during API call")
End Try
Can someone point me in the right direction to loop through all rows found?
My code currently checks the first item found only, which is not ideal as if that job fails, everything else gets held up.
Thanks
FOR EACH loop was the answer.
something like this...
For Each jobRow As DataRow in dtJobResults.Rows
Try
what I want to do for each returned row.
Catch Ex as exception
messagebox.show("Oh no, something went wrong!")
End Try
Next
I'm having some issues getting my data flow to do what I want it to.
I'm using an OLEDB Source that calls a stored procedure that uses a table variable to show me the data that I need to use.
It looks like this:
ClientID TimeStamp IsStart
pic#psdfj 2013-08-28 14:22:59 1
bsd#fjskk 2013-08-28 14:43:21 1
pic#psdfj 2013-08-28 15:23:01 0
..and so on
I need to create two new columns, one with the timestamp, and the other with the IsStart column addded up. (I'm keeping track of when users are online and capturing the timestamp.)
So I have a currently empty table in my SQL Server db called tblUserUsage, with the columns:
tblUserUsage (example of what the data would look like)
TimeStamp NumberOfUsers
2013-08-28 14:22:59 1
2013-08-28 14:43:21 2
2013-08-28 15:23:01 1
I'm having issues getting my data flow to output to those columns. Right now I have the storedprocedure call connected to a Derived Column, then to a script. But that isn't working as it's not letting me output to the outputbuffer in the script when I create output columns. Just for clarification - the script will be in VB.NET
This is what my script looks like so far. I have a NumberOfUsers column added to the output. But I still have no Output0buffer
Anyone have any ideas?
You only get an OutputBuffer generated in your code for asynchronous transforms (where the SynchronousInputID property of one or more outputs is set to zero). For synchronous transforms, your output columns will be in the InputBuffer.
Compare the MSDN articles Creating an Asynchronous Transformation with the Script Component and Creating a Synchronous Transformation with the Script Component.
Did you add a column to your output like this?
Then your output buffer would look something like this:
TableOutputBuffer.OutputColumnName = "hello";
Take a look a this sample I found here and maybe compare it to your code.. I usually write my scripts in c# so I can tell you if you're missing anything off the top of my head, but it might be worth a try.
Public Class ScriptMain
Inherits UserComponent
Dim connMgr As IDTSConnectionManager100
Dim sqlConn As SqlConnection
Dim sqlReader As SqlDataReader
Public Overrides Sub AcquireConnections(ByVal Transaction As Object)
connMgr = Me.Connections.MyADONETConnection
sqlConn = CType(connMgr.AcquireConnection(Nothing), SqlConnection)
End Sub
Public Overrides Sub PreExecute()
Dim cmd As New SqlCommand("SELECT AddressID, City, StateProvinceID FROM Person.Address", sqlConn)
sqlReader = cmd.ExecuteReader
End Sub
Public Overrides Sub CreateNewOutputRows()
Do While sqlReader.Read
With MyAddressOutputBuffer
.AddRow()
.AddressID = sqlReader.GetInt32(0)
.City = sqlReader.GetString(1)
End With
Loop
End Sub
Public Overrides Sub PostExecute()
sqlReader.Close()
End Sub
Public Overrides Sub ReleaseConnections()
connMgr.ReleaseConnection(sqlConn)
End Sub
End Class
When using a Linq-to-SQL class, how can I make a simple copy of an entity and save it?
My entity has a guid for a unique ID that gets automatically generated in the SQL Server.
I don't require a "deep clone".
I tried to use some clone methods that are out there but I couldn't figure out how to get everything serialized that needed to be serialized (got stuck on the DataContext not being serializable).
Can I just get an entity, detach it from the DataContext, null out the unique ID and InsertOnSubmit in a new DataContext? If so, how would I do this?
VB.net code preferred but not required.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
UPDATE:
Public Shared Function ReIssue(RequestID As Guid) As Guid
Dim req As Request
Dim new_req As Request
Using dc1 As New MBDataContext()
req = (From r In dc1.Requests Where r.ID = RequestID).Single()
End Using
new_req = req
new_req.ID = Guid.Empty
new_req.CreateDate = Nothing
Using dc2 As New MBDataContext()
dc2.Requests.InsertOnSubmit(new_req)
dc2.SubmitChanges()
End Using
End Function
I get an error: An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported.
on this line: dc2.Requests.InsertOnSubmit(new_req)
Nulling out the unique id and then calling InsertOnSubmit is the right way to go. Some things you have to consider though:
What is the type of the id? Is it an int? A Guid? Is it nullable? If it is nullable, make sure to set it to null, if it is an int, then to 0, or a Guid, then to Guid.Empty.
Does the type have a timestamp of some kind? If so, then you have to reset/set it to null as well, depending on the type.
Once you've done that, you can call InsertOnSubmit and then SubmitChanges and the change should take place.
Note, if you are doing this for a large number of records, you are better off writing a stored procedure which will perform the insert into the table using a select from the other table. It will be much faster that way (you won't be loading the data from the database into memory then pushing it back, inserting the records one at a time).
This method seems to have worked perfectly.
Making the final code look like this:
Public Shared Function ReIssue(RequestID As Guid) As Guid
Using dc As New MBDataContext()
Dim req As Request
req = (From r In dc.Requests Where r.ID = RequestID).Single()
Dim new_req As Request = DirectCast(Entity.Copy(req, New Request()), Request)
dc.Requests.InsertOnSubmit(new_req)
dc.SubmitChanges()
req.ActiveRequestParentID = new_req.ID
dc.SubmitChanges()
Return new_req.ID
End Using
End Function
Public NotInheritable Class Entity
Private Sub New()
End Sub
Public Shared Function Copy(source As Object, destination As Object) As Object
Dim sourceProps As System.Reflection.PropertyInfo() = source.[GetType]().GetProperties()
Dim destinationProps As System.Reflection.PropertyInfo() = destination.[GetType]().GetProperties()
For Each sourceProp As System.Reflection.PropertyInfo In sourceProps
Dim column As ColumnAttribute = TryCast(Attribute.GetCustomAttribute(sourceProp, GetType(ColumnAttribute)), ColumnAttribute)
If column IsNot Nothing AndAlso Not column.IsPrimaryKey Then
For Each destinationProp As System.Reflection.PropertyInfo In destinationProps
If sourceProp.Name = destinationProp.Name AndAlso destinationProp.CanWrite Then
destinationProp.SetValue(destination, sourceProp.GetValue(source, Nothing), Nothing)
Exit For
End If
Next
End If
Next
Return destination
End Function
End Class