VB6/Microsoft Access/DAO to VB.NET/SQL Server... Got Advice? - sql-server

I can make a DAO recordset in VB6/Access do anything - add data, clean data, move data, get data dressed in the morning and take it to school. But I don't even know where to start in .NET.
I'm not having any problems retrieving data from the database, but what do real people do when they need to edit data and put it back?
What's the easiest and most direct way to edit, update and append data into related tables in .NET and SQL Server?

The DataSet class is the place to start. As the linked article says, the steps for creating a DataSet, modifying it, then updating the database are typically:
Build and fill each DataTable in a DataSet with data from a data source using a DataAdapter.
Change the data in individual DataTable objects by adding, updating, or deleting DataRow objects.
Invoke the GetChanges method to create a second DataSet that features only the changes to the data.
Call the Update method of the DataAdapter, passing the second DataSet as an argument.
Invoke the Merge method to merge the changes from the second DataSet into the first.
Invoke the AcceptChanges on the DataSet. Alternatively, invoke RejectChanges to cancel the changes.

A natural progression IMO from DAO is ADO.net. I think you would find it pretty easy to pick up having the understanding/foundation of DAO. It uses DataAdapters and DataSets similar to recordsets. Modifying Data in ADO.NET.
I would suggest looking into Linq when you get a chance.

Is there a reason why ms-access was added as a tag here? It seems to me that the question has nothing but the most trivial relevance to Access, since once you're working with .NET, Access is completely out of the picture.

try to use oledbConnection , oledbCommand and oledbDataReader
from System.data.oledb
if you are using sqlserver DB, then use SqlConnection , sqlCommand and sqlDataReader
from System.data.SqlClient

Related

How to log custom metadata/context info with each query

I'm making extensive use of Entity Framework, and I need to optimize a lot of DB work.
I see many inefficient queries running in sys.dm_exec_sessions etc, but the problem is I don't have much context as to which code is initiating this query.
is there a way in EF to add some 'context' to each query, which can be viewed in the sys.dm_ queries?
pseudo-code:
dim d=mydbcontext
d.ContextInfo="Report Window 99"'???
dim results=d.set(of client).ToList
And then when I view SQL Servers log, I'll see next to each query the 'ContextInfo' that I set.
I see that SQL Server has a field context_info, but I haven't manage to see it in sys.dm_exec_sessions, also I have no idea how to set it via EF (and its limited to numeric values)
Thanks so much!
heres a very simple way
Dim csb = New SqlConnectionStringBuilder(cs)
csb.ApplicationName = "all my logging info..."

Setting a form's recordset via VBA is also setting its recordsource

I have an Access 2010 database that's linked to a SQL Azure backend (yes, I know this isn't ideal, and it's being slowly phased out). On the backend, I have a stored procedure that I want to use to populate a read-only subform each time a new record is loaded. I'm attempting to do this by generating a recordset in VBA, then setting the subform's RecordSet property. It actually works, but with a nasty side-effect.
When I set the RecordSet property, it also seems to be setting the RecordSource property of the subform. That RecordSource is something Access can't parse, because it's meant to be a call to the backend. If I try using a DAO passthrough query to generate the recordset, the RecordSource looks like:
EXEC dbo.GetDuplicateAddressesByManufacturer N'...', N'...', N'...'
If I try using an ADO command to generate the recordset, it looks like:
{ call dbo.GetDuplicateAddressesByManufacturer ?, ?, ? }
As soon as I try to move to the next record, Access throws an error because it tries to load a new record for the subform first, and it can't open what it sees as the subform's RecordSource. If I'm trying the DAO route, it tells me "Invalid SQL Statement", and if I'm using ADO, it tells me "Data provider could not be initialized."
Anyone have an idea how I can get around this? Isn't there a way to set the RecordSet property without also setting the RecordSource? I could swear I've done that before, but maybe I've just never noticed that the RecordSource gets set too.
Failing that, is there a way I can interject some code before the Form_Current event to remove the subform's RecordSource? The code I'm using to set the RecordSet each time works great -- the problem is the error that's raised before my code works. Once I dismiss the error message, everything works fine, but obviously I don't want users to get an error message each time they change records.
If all else fails, I guess I could always use the query to populate a local temp table, but it seems like a lot of overhead to do every single time someone moves to a new record.
Why bother with a stored procedure? Just link the sub form to the table, and setup the link master/child settings. You only pull down the required records.
If the sub form is a complex query with multiple tables, then you certainly want the data joins etc. to occur server side and AGAIN simply create a view and again set the sub form source to that view (and again the link master/child settings will do all the dirty work for you).
And there no reason why you cannot create a pass-through query and SIMPLE assign that to the forms recordSource.
It does not matter what “junk” you place inside of the query, and that includes RAW T-SQL.
And while you can load up the DAO reocrdset with this pass-thought, you really don’t need to. I suppose for some happy reason you are doing this, and at least if you must, then recordSoruce becomes the name of the pass-though and NOT your raw T-SQL anyway.
However, really, just dump all that recordset junk, and just go:
Me.MySubForm.Form.RecordSource = "my pass though query".
Thus above is only one line.
You doing all these hand stands to increase performance then at the end of the day why does your main form allow navigation? You should build a search screen, display the results, let user pick a row and THEN launch the main form to edit/display the ONE record along with the sub form data.
When they close, they are back to searching for the next customer etc. This approach also thus solves your messy navigation issues. It also why the web and most software works this way (it reduces bandwidth issues).
However, if you must have navigation, and for some reason CANNOT use a view and cannot let Access use the link master/child settings to do your dirty work?
Then in the forms on-current event you can modify the pass-though and simply re-assign it to the sub form.
Eg:
With CurrentDb.QueryDefs("qPass")
.SQL = "select * from FaxBook3 where id = 3"
End With
'
Me.RecordSource = "qpass"
Now how in the above I am using RAW T-SQL in the pass-though query, and then simply assign the pass-though to the forms recordsource (in your case you assign to the sub form.
Me.MySubForm.Form.RecordSource = above
And there NO reason why the above .SQL cannot be your stored procedure
.SQL = "Exec your-storedProcedure " & strVbaStringParmater
And again assign the form (or sub form) recordSource.
So you REALLY do not need to create some reocrdset in code and it not yield you any performance increase, but will cause you to write more code and have problems as you outlined in your post.

How to raise an event in VB.NET when a row is added to an SQL Server table

Not sure this is possible. Currently, to detect that a row has been added to a table in SQL Server, I use a timer to query the table. Is there a way SQL Server (presumably via the ADO.NET SqlConnection object) can raise an event in Visual Basic when a row is added, so I don't need to keep polling/querying the database?
If you are using SQL Server 2005+, you can use Service Broker and Query Notifications. The the setup is a bit complicated. In short you use SqlDependency Class.
The dependency first has to be created
System.Data.SqlClient.SqlDependency.Start(CS)
And then it can be used
Dim Cmd As New SqlCommand(SQLQuery, cn)
cmd.CommandText = "select field from dbo.MyTable"
sqlD = New SqlDependency(Cmd)
cn.Open()
Dim tbl As New DataTable
tbl.Load(Cmd.ExecuteReader)
AddHandler sqlD.OnChange, AddressOf TableChanged
The dependency should not be used by lot of clients and there are strict rules (Creating a Query for Notification) how the query should be written.
You could add a trigger to your table that calls your application whenever an updated happens. But I guess polling would be cleaner than calling your app from the database. Just keep the request small and if there's a change load the full data you need.
You can always add a trigger to the table and from there call a webservice. If there a lot of data being added, I would suggest keeping to your current method and call the database periodicaly.
You could always add a "item not process" table. Add an item in this table when something is being inserted and just query this table (which will be smaller).
There's also tutorial on how to call .net dll from SQL but I don't know enought to suggest it.

Concept of a database driven program in VB.NET

I have been developing programs in VB.NET for a few years and am familiar with it. The area where I do not have a lot of exposure is databases.
I am writing a program (for my personal use) called movie manager. It will store information on movies I have. I have selected Sql Server Compact Edition database. Assume I have a database with two tables namely Info and Cast. Info table has a few columns such as movie_name, release_date and so on. Cast table has few cols such as first_name,last_name etc.
Right now I have created a DataSet which reads all the info of tables from database (opens connection, fills tables info, closes connection). This way in a global variable I have a snapshot of database.
My queries :
Once I have data with me, every time I need to add, edit or delete a record I have to open a connection, fire an sql and close the connection. Right ? Is there a way to do this without using Sql ? Plus is this concept okay.
Since I am not using structures so I need to create empty datasets to store temp information. Is this convenient ?
If I have to search for a specific thing in dataset table, then do I have to loop thru all items or can I use sql on dataset or is there an alternate ?
1)Once I have data with me, every time I need to add, edit or delete a record I have to open a connection, fire an sql and close the connection. Right ? Is there a way to do this without using Sql ? Plus is this concept okay.
No. To update a database, you have to use the database. Create a stored procedure in the database to handle your functionality and then call it from the code and pass in whatever data needs saved. DO NOT USE INLINE SQL. Paramterized stored procedures are the way to go.
2) Since I am not using structures so I need to create empty datasets to store temp information. Is this convenient ?
It depends on what you're doing. I would create an object model to retain my updated data and then I'd pass the properties into the stored procedure when it was time to save my changes.
3) If I have to search for a specific thing in dataset table, then do I have to loop thru all items or can I use sql on dataset or is there an alternate ?
You can loop the rows or you can use linq to pull what you need out. Linq is really nice as it's basically .NET coded queries against a collection.
There are plenty of tutorials/guides out there to show you how to update via stored proc call form your code. There are a ton of linq tutorials as well. Basically, a linq query against your table will look something like:
dim result as Generic.List(of String) =
(from r in table.AsEnumerable()
select r
where r["columnName"] = "the value").ToList()
This syntax is probably a bit off, but it looks something like that.
Edit
Your Model:
Public Class EmployeeModel
Public Property Id
Public Property FirstName
Public Property Last Name
Public Property JobCode
Public Sub EmployeeModel(your params)
//set properties
End Sub
End Class
Your DAL:
Public Shared Class EmployeeDAL
Public Shared Sub SaveEmployee(ByRef model as EmployeeModel)
// call your sp_SaveEmployee stored procedure and set the parameters to the model properties
// #id = EmpoyeeModel.Id
// #JobCode = Employee.JobCode
// ...
End Sub
End Class
I use VB every few months, so there are probably some small syntax errors in there. But that's basically all you need to do. The function to save your data is in the DAL, not in the class itself. If you don't want to use a DAL, you can put the save functionality in your class, though. It'll work the same way, it's just not as clearly separated.
On your Questions.
number 1: You have to connect to database in order to store and retrieve data. There are lots of ways on how to deal with it and one way of it is to use app.config or you may simply create a function that calls the connection every time you need it.
number 2: Since you are dealing with dataset here are some tips you might want to look at DataSet
number 3: You can also try using Data Adapter and Data Table. I am not sure what you meant by your question number 3.
Cheers
I have problem with the way you are using your database and the ram of your computer.
Problem1: since you already have a database for holding the movies information why are you again holding the same information in memory?, creating an extra overhead. if your answer is for performance or i have cheap memory then why don't you use xml or flatfile instead? Database is not needed with this senario.
Problem2: You are like a soldier who dosent know about the weapon he use? right? because you are asking silly questions your first question about opening connection.. the answer is yes you have to open the connection every time save/read the data and close it as soon as possible.
your second question about convinent the answer is no. instead create class with all field as property and some method for initialization,saving,deleting. this way you have to write less code. nad suppose you have a movie names xyz there can be another movie xyz how will you distinguish it? if you have whole information b4 you you can do it via release date ,casts etc, but still it will be hard, so create a primary key for both your table
and finally your 3rd question , it will be easier to use use sql queries than looping thru the dataset(get rid of the dataset as soon as possible)
wish yu good luck on the road to rdbms

executing insert\update\deletes - Use Linq?

I was looking at using linq to sql (or EF) rather than in line\dynamic sql within my application but have hit a possible issue. My application modifies data against any number of random databases accross several sql instances, linq appears to structured towards a single database scenario. Would it be best to just continue using in line sql or is there a method of using linq without tying it down to a single database?
An example of what I'm doing at the moment:
Using cn As SqlConnection = (ConnectionString)
Using cm As SqlCommand = New SqlCommand("< Dynamic sql>;", cn)
cn.Open()
cn.ChangeDatabase(Database)
cm.ExecuteNonQuery()
End Using
End Using
And example of a query would be:
DELETE FROM settings WHERE [Sec] = 'ON' AND [Key] = 'last'; INSERT Settings([Sec], [Key], [Val]) values('ON', 'last', GETDATE());
Although I am executing stored procedures within these databases, some custom, others for adding users (sp_adduser)
All target databases have the same structure, so any query\linq would work against it.
With LINQ, you are correct in that a DataContext goes to one single database, but you can have many DataContexts, each going to a different database. You can have, for example, a SettingsDataContext going to the database with your settings and a UsersDataContext going to the database with your users, or however you have it set up.
There is the syntax of it all. Here is a link to some examples of doing inserts and selects with ADO.NET and Linq to SQL.
http://blogs.msdn.com/b/wriju/archive/2008/07/14/linq-to-sql-vs-ado-net-a-comparison.aspx
One thing I have heard often is that Linq to SQL is for those that aren't real comfortable with SQL or who just like to work in the realms of C# or VB.NET code more than having to switch thought patterns and think in the ADO.NET/inline SQL realm.

Resources