Using VS 2013 (VB) and SQL server 2016.
I have linQ query that returns two columns from a database. The query is as follows.
Dim val = (From value In db.ngc_flowTypes
Where value.defaultValue IsNot Nothing
Select value.flowName, value.defaultValue)
The data it returns is a as follows.
I want to iterate through each row of the results and pass the values to certain variables. A ForEach statement doesnt seem to work as it just runs through once. I am sure this must be easy but I ont quite understand it. Am I getting the data returned in the best way via my query? Can I transpose the data to a data table in VB? so I can work with it easier?
The end result I want is string for each flow name with its corresponding default value (along with some other text). So something like this.
dim strsubmission as string = flowName + " has a value of " + defaultValue
Use ToDictionary.
Dim val = (From value In db.ngc_flowTypes
Where value.defaultValue IsNot Nothing
Select value).ToDictionary(Function(key) key.flowName,
Function(value) value.defaultValue)
This will actually execute the SQL of the linq on the database (approx. Select * From ngc_flowTypes Where defaultValue Is Not NULL), traverse each record into a key/value pair (flowName, defaultValue) and put it into a in-memory dictionary variable (val).
After that you can do whatever you like with the dictionary.
For Each flowName In val.Keys
Console.WriteLine("{0} has a value of {1}", flowName, val(flowName))
Next
Edit:
This will only work as long flowName is unique in table ngc_flowTypes
Related
I am using SQL Server 2016.
I have a stored procedure GET_RECORDS that takes input parameters for filter and outputs a CURSOR parameter
I want to get this cursor in my SSIS package
I had created data flow task, OleDb source and variables for parameter values. Then mapped parameters
Params mapping screen
but when I wanted to save the component - I got an error
error screen
I tried to add clause WITH RESULT SETS with some dummy columns, but my procedure doesn't return any result set
What am I doing wrong?
Any advices will be helpful.
Thank you.
With regards, Yuriy.
The source component is trying to determine what columns and types will be returned. Because you are using dynamic SQL the metadata can change each time you run it.
With result sets allows you to define the data being returned but should only be used if you are guaranteed to have those results every time you execute.
EDIT:
I create a connection and run the command so that it populates a data table. Then I put the column headers into a string array. There are plenty of examples out there.
Then I use the following function to create a destination table. Finally I create a datareader and pass that to the .Net SqlBulkCopy. Hope this helps.
private void CreateTable(string TableName, string[] Fields)
{
if (TableExists(TableName) && Overwrite)
{
SqlCommand = new SqlCommand($"Drop Table [{TableName}]", SqlConnection);
SqlCommand.ExecuteNonQuery();
}
string Sql = $"Create Table [{TableName}] (";
int ColumnNumber = 1;
foreach (string Field in Fields)
{
string FieldValue = Field;
if (! HasHeaders)
{
FieldValue = "Column" + ColumnNumber;
ColumnNumber++;
}
Sql += $"[{FieldValue}] Varchar(8000),";
}
Sql = Sql + "ImportFileID Int, ID Int Identity(1,1) Not Null, Constraint [PK_" + TableName + "] Primary Key Clustered ([ID] Asc))";
SqlCommand = new SqlCommand(Sql, SqlConnection);
SqlCommand.ExecuteNonQuery();
}
Use ado.net source instead of oledb source, define a simple select and get the columns you wish to return. Now you can define expresión in the dataflow properties.
Search ado.net source dynamic sql
:)
try to return the records and use foreach in ETL instead of cursor
https://www.simple-talk.com/sql/ssis/implementing-foreach-looping-logic-in-ssis/
I think you can do it from a simple way, but I don't know what you are you doing, exactly...
Which one could be a better practice? In my situation, I need to check if a specific data exists in a table. I am iterating through an Excel file and verifying if a code there exists in my table using VB.NET. I have two options to do this (or if there is a better way to do this, I am open for suggestions).
First is to check it one by one, this code is executed per loop:
SQL = "SELECT TOP 1 * FROM Table1 WHERE Code = '" & codeFromExcel & "'"
rs = dbConn.Execute(SQL)
If Not rs.EOF Then
isFound = True
Else
isFound = False
End If
The other one is I load all the codes in a List(Of T)
Dim myList As New List(Of String)()
rs = Nothing
rs = dbConn.Execute("Select Code from Table1")
If Not rs.EOF Then
Do While Not rs.EOF
myList.Add(rs.Fields("Code").Value.ToString)
rs.MoveNext()
Loop
End If
Then check every record if it is in the List(Of T) while iterating in the Excel.
If myList.Contains(codeFromExcel) Then
isFound = True
Else
isFound = False
End If
I've been working with this kind of stuff most of the time and I want to know which one is the most efficient way to use. At the moment I only have a few records in my database. I want my code to be ready and efficient when the time comes that I need to deal with numerous records. Thanks in advance!
Additional info: The data doesn't need to be "fresh" as that table is meant for one-time entry only.
Personally I prefer to open as less connections to data base as possible.
So:
If the table is not very large (some hundred rows) I would go with the "cache" option.
Generally:
I would gather all excel codes in a list. ( excelCodes )
Then I would query something like Select Distinct Code from Table1 Where Code In ( excelCodesList ) and store it in a second list ( foundCodes ).
Then I would compare these lists.
I test it on a table with 6.143.993 rows.
To select just one column (description) to "cache" took 1'29".
On the other hand query like:
select distinct description from ItemDetail where description in ( 'abc','cddd','xxx' )
took 0'58".
UPDATE
An index on Code column might help with performance.
My query in SQL Server is sorted by several factors, and when I execute it the ordering is all correct. I have some subforms that are populated using the following code:
Set db = OpenDatabase("", False, False, globalstrSQLConnection)
strSQL = "SELECT * FROM qryTaskSimple"
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot, dbSeeChanges)
Set Me.Recordset = rs
where globalstrSQLConnection is the connection to the database on my my SQL Server and qryTaskSimple is the query mentioned above. But the subforms are sorted by a completely different criterion. Instead of being sorted by:
ORDER BY CASE WHEN tblTask.JobNum LIKE '***FULL***' THEN 0 ELSE 1 END, DivisionSortID, SuperintendentSortID, ISNULL(dbo.tblTask.Ordering, 999999999),
dbo.tblTask.JobNum, dbo.tblTask.Sequence
as stated inside the query, it seems to be sorted by only tblTask.JobNum... even when I replace the entire ORDER BY clause with ORDER BY DivisionSortID... And I don't have any VBA code that further sorts the subforms.
Queries and tables in Access have an underlying query/table object order by that can over-ride the SQL order by. You can see it (and remove it) in respective object properties.
It can be pretty frustrating and I'm not really sure if that's what's going on, but regardless, you can force desired sorting by simply adding it to your SQL statement, treating the query as a table.
strSQL = "SELECT * FROM qryTaskSimple ORDER BY <your desired sorting using any qryTaskSimple cols>"
if that doesn't work, then try the (sub)forms orderby at the form's load() event:
Private Sub Form_Load()
me.orderby = "your order by statements"
if me.orderbyon = false then me.orderbyon = true
End Sub
I am very new to DB application development, though I have a fair amount of experience in VB.NET and C++ (self-taught, somewhat intermediate). I have a query in a table adapter with two parameters (user input) that always returns only one row from a table, based on those two parameters. Let's say row X with A, B and C columns. Filters are set on A and B in my query, but it selects all fields.
Now, I want to show the value of C in one of my main Form objects (let's say a Label in this example), but I cannot seem to be able to extract it. I know it probably is very easy, but I am a bit lost in DB code jungle..
[EDIT]
My apologies, the code bit (example).
Query:
SELECT Column1, Column2, Column3
FROM Table1
WHERE (Column1 = #Parameter1) AND (Column2 = #Parameter2)
In my VB project:
Dim temp
temp=Me.Table1TableAdapter.queryName(Me.MyProjectDBDataSet.Table1,userinput1, userinput2)
Up to this point everything works perfectly, but this is also where I get stuck. How do I, let's say, assign the value of Column3 (after running the query the result will always be only one row from Table1) to Label.Text for instance?
I hope this makes it a bit clearer..
Dim db As Database = DatabaseFactory.CreateDatabase
Dim cmd As DbCommand = db.GetSqlStringCommand(query) 'Query is a string containing your SQL command'
Dim sqlDataReader As IDataReader = db.ExecuteReader(cmd)
Dim myObj As New MyObject
If sqlDataReader IsNot Nothing Then
'Loop through the rows of the DataReader'
Do While sqlDataReader.Read()
'Do something here with the value in Column3'
myObj.myIntegerProperty= CInt(IIf(IsDBNull(.Item("Column3")), 0, .Item("Column3")))
Loop
End If
I am trying to get the data from SQL Server database.
I have a table called Standard in my database. It has three columns StandardID, StandardName, and Description.
I have a combobox in which I fill the values of StandardName
Here is the code :
Using db As New SchoolDBEntities
ComboSelectStandardToEdit.DataSource = db.Standards.ToList()
ComboSelectStandardToEdit.ValueMember = "StandardID"
ComboSelectStandardToEdit.DisplayMember = "StandardName"
End Using
Now I have 2 textboxes called txtStandardName and txtDescription.
I want to fill the values of these 2 textboxes based on selected StandardName from the combobox.
Here is the code I tried :
Using db As New SchoolDBEntities
Dim standard = From s In db.Standards
Where s.StandardId = CInt(ComboSelectStandardToEdit.SelectedValue)
Select s
txtStandardName.Text = CType(standard, Standard).StandardName
End Using
but unfortunately I got error :
Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery`1[EF_WinForms_VB.Standard]' to type 'EF_WinForms_VB.Standard'.
try using
Dim standard = (From s In db.Standards
Where s.StandardId = CInt(ComboSelectStandardToEdit.SelectedValue)
Select s)
.FirstOrDefault
txtStandardName.Text = standard.StandardName
your Linq query currently is returing a projection which could contain multiple entries. By explicitly requesting the first object of the projection, you won't need to cast your standard before accessing it's value.
Try using
Dim standard = (From s In db.Standards.AsEnumerable
Where s.StandardId = Convert.ToInt32(ComboSelectStandardToEdit.SelectedValue)
Select s)
.FirstOrDefault
txtStandardName.Text = standard.StandardName
Hope it helps.