public function to create and open a database connection - database

I have a client/server desktop application that I am having some database connection issues with on some of my clients pc's. When I wrote the app, I didn't know any better so I created and opened 1 database connection on application startup, and used that same connection all throughout the app. I know realize this is a bad idea since shaky network connections and it seems antivirus programs are causing these connection to be dropped at times, leading to some errors. I have hundreds of places in code where I need to go back and create/open/close the connection at the time they are being used.
The question is, is there any way to create a public function in which I can do just that, and then do a global find and replace to replace the connection name with the new function name?
something like:
Dim qry As NpgsqlCommand
sqlUpdateItem = "update table set field = value where id = 1"
qry = New NpgsqlCommand(sqlUpdateItem, con)
qry.ExecuteNonQuery()
to
Dim qry As NpgsqlCommand
sqlUpdateItem = "update table set field = value where id = 1"
qry = New NpgsqlCommand(sqlUpdateItem, newCon())
qry.ExecuteNonQuery()
public function newCon()
Dim con As New NpgsqlConnection(connectionString)
con.Open()
Return tcon
End Function
I tried this but no luck. I'm just looking for any possible solutions that don't involve me updating several lines of code in hundreds of places throughout my app. The nice thing is I would only need to do this for all commands, since I can pass a brand new connection into a data adapter and it will handle the opening/closing.

Here's an example of how I'd recommend you attempt it.
Enable option strict in your project. It's better to have your errors at compile time than at runtime.
Use a using statement to safely dispose of the database classes even if you get an exception.
Private _connectionString As String = "blah"
Public Function GetDbConnection() As NpgsqlConnection
Dim con As New NpgsqlConnection(_connectionString)
con.Open()
Return con
End Function
Public Sub DoMyQuery()
Using conn = GetDbConnection()
Using qry = New NpgsqlCommand("update table set field = value where id = 1", conn)
qry.ExecuteNonQuery()
End Using
End Using
End Sub

Related

VB.NET ADODB MS SQL Server Open Recordset

After I open a SqlConnection, I try to open a recordset like I did it thousands times before in VBA. Yes, I know that there are differences between VBA and VB.NET, but maybe it's to simple to see it.
Public Class Form1
Const m_cstrCnnString As String = "MyCorrectCnnString"
Dim cnn As SqlConnection
Dim rcs As New ADODB.Recordset
Private Sub MyConnection()
cnn = New SqlConnection(m_cstrCnnString)
cnn.Open()
'so far it works, my cnn.State is 1
rcs.Open("SELECT * FROM dbo.myTable", cnn) 'this line doesn´t work
End Sub
I tried the rcs.Open with and without CursorTypeEnum, LockTypeEnum, but I always get the same error:
System.Runtime.InteropServices.COMException: The arguments are of the wrong type, are out of scope, or are inconsistent with each other.
Background: Win10, Connection to a MS SQL Server Express by VB.NET.
First I import System.Data.SqlClient
Microsoft ActiveX Data Objects 6.1 Library is activated.
Also I tried it with Microsoft ActiveX Data Objects Recordset 6.0 Library.
And I'm new in VB.NET
There's some high-level stuff I need to cover before we can get into the details of what this code should look like.
First, if you're using VB.Net, you should not be opening a RecordSet object. Recordset is from ADO, which is not the same as ADO.Net. You definitely can't use an ADO.Net SqlConnection to open a classic ADO RecordSet. Again: these are two completely different libraries. The classic library exists in .Net only for backwards compatibility and to aid in porting forward old code. It should not be used for new development.
Additionally, when you move forward to ADO.Net you need to be aware of a feature called Connection Pooling. This feature takes care of caching connection objects for you, such that it's counter-productive (uses more RAM and makes things slower) to try to keep a single connection option ready for use throughout the application. Instead, it really is better to create a new connection object for most queries.
Finally, classic ADO had a problem with properly closing resources, such that some of those older applications could occasionally even lock out the database. .Net provides a way to handle this such that you are sure everything is closed and disposed properly and promptly: a Using block.
The weakness of this mechanism is DataReader objects (which replace RecordSet) need the connection to remain open for the life of the reader. This makes it hard to build a good data abstraction to hide all the boiler plate code that goes with data access.
The best pattern I've seen for offering the best of both worlds requires some moderate and advanced VB.Net language features (lambda methods, iterator blocks, and IEnumerable) that are unfamiliar to many traditional VB coders. It's going to require me to go a lot deeper than normal in this answer. That said, once you wrap your head around it, the result is really nice.
To show what this might look like, I need an example that's a little more concrete. We'll pretend you have an Employee table with columns for ID, FirstName, and LastName, and a class Employee with properties of the same name:
Public Class Employee
Public Property ID As Integer
Public Property FirstName As String
Public Property LastName As String
Public Shared Function FromDataRecord(record As IDataRecord) As Employee
Return New Employee() With {
ID = record("ID"),
FirstName = record("FirstName"),
LastName = record("LastName")
}
End Function
End Class
That's right: VB sometimes uses braces now. The Shared method at the end is optional, but it will help make some of what comes next easier to follow. Here is what modern ADO.Net code might look like. Pay special attention to the use of Private and Public
Public Module DB
Private Shared Property ConnectionString As String = "MyCorrectCnnString"
Private Iterator Function GetData(Of T)(SQL As String, transform As Func(Of IDataRecord, T), addParameters As Action(Of SqlParameterCollection)) As IEnumerable(Of T)
Using cn As New SqlConnection(ConnectionString)
Using cmd As New SqlCommand(SQL, cn)
If addParameters IsNot Nothing Then addParameters(cmd.Parameters)
cn.Open()
Using rdr As SqlDataReader = cmd.ExecuteReader()
While rdr.Read()
Yield transform(rdr)
End While
End Using
End Using
End Using
End Function
Public Function GetEmployees() As IEnumerable(Of Employee)
Dim SQL As String = "SELECT * FROM dbo.Employee"
Return GetData(SQL, Employee.FromDataRecord, Nothing)
End Function
Public Function GetEmployeeById(ID As Integer) As Employee
Dim SQL As String = "SELECT * FROM dbo.Employee WHERE ID= #ID"
Return GetData(SQL, Employee.FromDataRecord,
Sub(pc) pc.Add("#ID", SqlDbType.Integer).Value = ID
).FirstOrDefault()
End Function
Public Function GetEmployeesByLastName(LastName As String) As IEnumerable(Of Employee)
Dim SQL As String = "SELECT * FROM dbo.Employee WHERE LastName= #LastName"
Return GetData(SQL, Employee.FromDataRecord,
Sub(pc) pc.Add("#LastName", SqlDbType.NVarChar, 25).Value = LastName
)
End Function
End Module
Now the main part of the application NEVER deals in SQL directly, or even has to know there's a relational database involved. It's just calling methods on a regular module, such that the code in your form for reading data looks more like this:
Dim employees = DB.GetEmployeesByLastName(TextBox1.Text)
DataGridView1.DataSource = employees
You make similar methods in the new Module for writing INSERT/UPDATE/DELETE queries to save changes. These methods will end up calling the cmd.ExecuteNonQuery() method, but they should NEVER accept an SQL statement string as input.
As an application grows you might have a number of classes with FromDataRecord() methods, such that you instead refactor these methods to their own Module. You might also end up with enough Public methods in the DB Module to divide them up into a number of related Modules. At this point, these Modules would all go into a separate class library project (using Friend in some places instead of Private).

Why is my vb code not updating the ms access database (only cached temporarly)

I am doing a small system using Ms. Access (the database has more than 10 tables ) connecting to visual studio. I made a public class for opening the connection to the database so I can use it in every form. Everything is working and I can get the data from the database But any inserting or deleting data in forms, the database in ms access not getting the update. I can see the new records in forms but nothing in the database.
Imports System.Data.OleDb
Public Class dbconnectClass1
'create db connection
Private DBcon As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=dental_clinic.accdb;")
'prepare db command
Private dbcmd As OleDbCommand
' db data
Public DBDA As OleDbDataAdapter
Public DBDT As DataTable
'query parameters
Public params As New List(Of OleDbParameter)
'query statics
Public recordcount As Integer
Public Exception As String
Public Sub ExecQuery(query As String)
'reset query status
recordcount = 0
Exception = ""
Try
'open connection
DBcon.Open()
'create db command
dbcmd = New OleDbCommand(query, DBcon)
'load params into dbcommand
params.ForEach(Sub(p) dbcmd.Parameters.Add(p))
'clear params list
params.Clear()
'excute command and fill dataset
DBDT = New DataTable
DBDA = New OleDbDataAdapter(dbcmd)
recordcount = DBDA.Fill(DBDT)
Catch ex As Exception
Exception = ex.Message
End Try
'close the database connection
If DBcon.State = ConnectionState.Open Then DBcon.Close()
End Sub
'include query and command parameters
Public Sub addparam(name As String, value As Object)
Dim newparam As New OleDbParameter(name, value)
params.Add(newparam)
End Sub
End Class
This my code inside the forms:
Public Class NewExpense
Private access As New dbconnectClass1
' a varuble having the appointment Id to connect between 2 forms
Private appointmentNo As Integer
Private Function NoError(Optional report As Boolean = False) As Boolean
If Not String.IsNullOrEmpty(access.Exception) Then
If report = True Then MsgBox(access.Exception)
Return False
Else
Return True
End If
End Function
Private Sub Savebuttum_Click(sender As Object, e As EventArgs) Handles
Savebuttum.Click
Dim oDate As DateTime = Convert.ToDateTime(DateTimePicker1.Value)
access.addparam("#expensenme", expensenmtXT.Text)
access.addparam("#expensedetail", ExpenseDetailTXT.Text)
access.addparam("#expenseamount", ExpenseAmountTXT.Text)
access.addparam("#expensedate", oDate)
access.addparam("#expensepaidTo", paidtoTXT.Text)
access.ExecQuery("INSERT INTO Expense (Expenses_name, expense_details,
expenses_amount, ExpenseDate_Paid, ExpensePaid_To) Values (#expensenme,
#expensedetail, #expenseamount, #expensedate, #expensepaidTo);")
'report on errors
If Not String.IsNullOrEmpty(access.Exception) Then
MsgBox(access.Exception) : Exit Sub
'success
access.DBDA.Update(access.DBDT)
MsgBox("Expense Has been Added Successfully")
End Sub
End Class
Hum, you have this:
params.ForEach(Sub(p) dbcmd.Parameters.Add(p))
Great, we add the parmaters - looks good to go!!!
then, next line CLEARS all the work above!!! (the parameters are removed!!!!)
'clear params list
params.Clear()
Next up? Many will build a connection object, then a reader, and then a adaptor. But you ONLY need a data adaptor if you going to update a data table. if you just going to execute a command, then you don't need the data table, and you don't need a adaptor FOR that table. Adaptor = ability to modify a existing datatable (or dataset).
You are MUCH better to use the command object.
Why?
Because the command object has a connection object (don't need a separate one)
Because the command object has a data reader for you (no need for a whole data adaptor to JUST fill a table. And remember, you don't need a whole data adaptor UNLESS you are going to send/update a data table back to the database.
And because the command object has the command text, then you don't even need a variable for that!!!
And because all objects are in "one object", then really all you need is something to handy get you the connection.
So, for your insert example, we really don't gain by having that object, do we?
Ok, so here is your insert code without using those extra objects:
so in the following, I declare ONE variable, - the sql command object.
And do the insert
And as FYI? Your save button is not a save - but a insert button - every time you hit it, you will insert a new row. Lets deal with that issue in a bit.
So, here is our code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Using cmdSQL As New OleDbCommand("INSERT INTO Expense
(Expenses_name, expense_details,expenses_amount, ExpenseDate_Paid, ExpensePaid_To)
Values (#expensenme,#expensedetail, #expenseamount, #expensedate, #expensepaidTo)",
New OleDbConnection(My.Settings.TESTOLEDB))
With cmdSQL.Parameters
.Add("#expensenme", OleDbType.WChar).Value = expensenmtXT.Text
.Add("#expensedetail", OleDbType.WChar).Value = ExpenseDetailTXT.Text
.Add("#expenseamount", OleDbType.Currency).Value = ExpenseAmountTXT.Text
.Add("#expensedate", OleDbType.DBDate).Value = DateTimePicker1.Value
.Add("#expensepaidTo", OleDbType.WChar).Value = paidtoTXT.Text
End With
cmdSQL.Connection.Open()
cmdSQL.ExecuteNonQuery()
End Using
So things in above:
We have strong data typing and converstion.
Because of this, note how I did NOT have to create a separate date/time variable here.
Note the SAME for "money" or so called currency conversion - again strong data type by using parameters this way.
And is this a date only, or a date+ time value? If it is date, then
.Add("#expensedate", OleDbType.DBDate).Value = DateTimePicker1.Value
If it was/is a date + time, then this:
.Add("#expensedate", OleDbType.DBTimeStamp).Value = DateTimePicker1.Value
So, notice how all your object stuff REALLY did not help one bit, and in fact you did not really save code, and above actually had LESS variables defined to do the whole job.
Now, back to the insert issue/problem. (you save is doing a insert). But what about editing existing records?
So, I would suggest you work out the problem this way:
You create/get/have/assume a data row for the form.
The form takes the data row, fills the controls. You edit, and when you hit save, the data row is sent back to the datbase. So, once this works, then to add? Well, the add code will CREATE a new data row, save to database and THEN you send that new data row to the above eixsting form that can edit a data row, and can save a data row. So the form now is able to deal with both issues (adding vs editing existing). If the user dont' want the row, then you offer a delete button.
And REALLY nice is a data row means you don't deal with SQL, and don't deal with parmaters!!
So the code (desing pattern) I use is thus this:
dim da as oledbDataAdaptor
dim myTable as DataTable = MyRstEdit("SELECT * from tblHotels WHERE ID = " & lngID,da)
dim MyDataRow as DataRow = myTable.Rows(0)
' code to fill controls
txtHotelName.Text = MyDataRow("HotelName")
txtCity.Text = MyDataRow("City")
' etc. etc. etc.
Now to save? Well I put the values back into that DataRow like this:
MyDataRow("HotelName") = txtHotelName.Text
MyDataRow("City") = txtCity.Text
MyDateRow("BookingDate") = txtTimePick1.Value
da.Update(MyTable)
Notice how I don't have parameters, and even strong data type checking occurs for say the above Date/Time booking date column.
And the above is nice, since I don't have to deal with ANY parmaters to udpate a row of data.
The MyRstEdit routine looks like this and returns byREf a "da" (data adaptor).
Public Function MyrstEdit(strSQL As String, Optional strCon As String = "", Optional ByRef oReader As SqlDataAdapter = Nothing) As DataTable
' Myrstc.Rows(0)
' this also allows one to pass custom connection string - if not passed, then default
' same as MyRst, but allows one to "edit" the reocrdset, and add to reocrdset and then commit the update.
If strCon = "" Then
strCon = GetConstr()
End If
Dim mycon As New SqlConnection(strCon)
oReader = New SqlDataAdapter(strSQL, mycon)
Dim rstData As New DataTable
Dim cmdBuilder = New SqlCommandBuilder(oReader)
Try
oReader.Fill(rstData)
oReader.AcceptChangesDuringUpdate = True
Catch
End Try
Return rstData
End Function
So, now in vb.net, I actually find it is LESS code then even writing + using recordsets in MS-Access VBA code.
However, BEFORE you go down ANY of the above road?
Have you considered using the vb.net data binding features. Data-binding in vb.net means that you do NOT write ANY of the above code. it means that vb.net will do all of the dirty work, and write and setup ALL OF the code for you to edit data on a form. The end result is you don't write any code to update a table.
You do have to use + create a "data set". Once done, then you just drag controls onto the form, and you even get this. So you just drop in a dataset, table adaptor, Binding navagator, and you get this:
Note now the tool bar at the top (and you can place it on teh bottom if you wish). So you get this:
So that WHOLE form was created without having to write ONE line of code. And you can see we have navigation, edits and saves and even the ability to add. So, you can build up a editing form - and it thus becomes similar to say working in MS-Access and ZERO lines of code is required to build the above form.
However, if you ARE going to roll your own code? Then use a data row. That way you can shuffle data to/from the table, and NOT have to use parmaters and SQL update and insert statements - but ONLY have nice clean code in which you shove, or get values from that data row. .net will "write" all the update stuff for you.

Exception with sqlite database "no such table"

First of all I´m developing a database with autosuggest box. I´ve created a database with DB Browser and imported data. I was reading documentation in C# how connect database and retrieve data. The issue is show up an exception error:
enter image description here
I´ve connected the database in properties with content option. I paste the code:
Public NotInheritable Class METARTAF
Inherits Page
Dim dbpath As String = Path.Combine(ApplicationData.Current.LocalFolder.Path, "airportsdb.sqlite3")
Dim conn As SQLite.Net.SQLiteConnection = New SQLite.Net.SQLiteConnection(New WinRT.SQLitePlatformWinRT(), dbpath)
Dim airportinfo As List(Of String) = Nothing
Public Sub New()
' This call is required by the designer.
InitializeComponent()
End Sub
Private Sub AutoSuggestBox_TextChanged(sender As AutoSuggestBox, args As AutoSuggestBoxTextChangedEventArgs)
Dim datairport As New List(Of String)
Dim retrieve = conn.Table(Of flugzeuginfo)().ToList
If args.Reason = AutoSuggestionBoxTextChangeReason.UserInput Then
If sender.Text.Length > 1 Then
For Each item In retrieve
datairport.Add(item.IATA)
datairport.Add(item.ICAO)
datairport.Add(item.Location)
datairport.Add(item.Airport)
datairport.Add(item.Country)
Next
airportinfo = datairport.Where(Function(x) x.StartsWith(sender.Text)).ToList()
sender.ItemsSource = airportinfo
End If
Else
sender.ItemsSource = "No results..."
End If
End Sub
Private Sub AutoSuggestBox_SuggestionChosen(sender As AutoSuggestBox, args As AutoSuggestBoxSuggestionChosenEventArgs)
Dim selectedItem = args.SelectedItem.ToString()
sender.Text = selectedItem
End Sub
Private Sub AutoSuggestBox_QuerySubmitted(sender As AutoSuggestBox, args As AutoSuggestBoxQuerySubmittedEventArgs)
If args.ChosenSuggestion Is Nothing Then
stationidtxt.Text = args.ChosenSuggestion.ToString
End If
End Sub
Anyone could help about this?
Before you query or insert into a table, you should CREATE it. This tells SQLite what columns you have and suggests datatypes (on other rdbms's you get actual data type enforcement but SQLite does not do that). If this is your problem, you will want to spend some time with the SQLite documentation on data types and the ability to hook them into your application.
On the other hand, as you seem to be trying to retrieve data, this suggess one of two things is wrong. Either you care connecting to the wrong db (in which case SQLite will usually helpfully create an empty db for you!) or else you are specifying the wrong table.

ASP Classic Getting and Setting the Conn to another Conn object

I am using this way to connect and use the Conn object for connections
<!-- #include file="dataconnections.asp" -->
In one of my ASP pages, I have a VBScript Onclick event that needs me to execute a stored procedure and pass the variables in the textboxes.
Right now, the Connection String is hardcoded in the ASP File itself and is not using the Conn object from the include file. Is there any proper way to execute the SP without using a new Conn, or how can I pass the current Conn from the include file to the one being used in the VBScript Onclick event?
I don't know what your include dataconnections.asp contains (would have been nice if you had posted the source code in your question) but a stored procedure is best run using the ADODB.Command object which exposes the ActiveConnection property.
This allows you to either Set your ADODB.Connection object or pass your connection string and let the ADODB.Command instantitate a new ADODB.Connection using that connection string.
Here are examples of using the two options
Use existing ADODB.Connection
Dim cmd
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
'Use existing object from include file to set connection.
Set .ActiveConnection = YourConnObject
End With
IMPORTANT: When using this method make sure the YourConnObject (ADODB.Connection) should have been opened using
'Make sure connection has been opened.
Call YourConnObject.Open()
before assigning to the ADODB.Command object.
Use connection string variable (probably defined in your include) to set the connection that will be exclusively used by the ADODB.Command object.
Dim cmd
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
'Use connection string to instantiate a new connection to be used
'exclusively by the ADODB.Command object.
.ActiveConnection = YourConnectionString
End With
NOTE: Unlike option 1 calling
'Close ADODB.Command object
Call cmd.Close()
Will instantaneously destroy the ADODB.Connection (that was assigned while setting the ActiveConnection property).
Useful Links
Using Stored Procedure in Classical ASP .. execute and get results

SQL Server Impersonation and Connection Pooling

I've been given the task of writing an web interface for a legacy database we have where all users have database accounts and are assigned roles accordingly (we have triggers all over the place recording when users do certain things, all based on user_name()).
In order to use anything remotely modern and to avoid storing the user's password in plain text I'm connecting w/ an App-level account that has impersonation privileges for each user, and I'm trying to run Execute As User=#username and Revert to set and reset the execution context before and after running any SQL.
Unfortunately, the connection pooling's reset_connection call is mucking w/ my Connection, and it winds up throwing some nasty errors about Physical connection being invalid...
I can get around this error by not using the connection pool. But then my application user needs an insane amount of privileges to actually perform the impersonation. Furthermore, killing connection pooling is a bummer...
How can I do this without sacrificing security or performance? Keep in mind I can't change the fact that my users have database logins, and I'm really not excited about storing user passwords in a retrievable manner. Is my only option bypassing the connection pool so I can impersonate (and using an sa user so I have sufficient permissions to actually impersonate someone)?
To implement a kind of "fake" delegation without huge changes in application/database code I propose using context_info() to transport the current user to the database and replace the calls to user_name() with calls to dbo.fn_user_name().
An example on how to build up this solution
Create fn_user_name() function
I would create a function fn_user_name which will extract the user name from the context_info() on the connection or return user_name() when there is no context info available. note that the connection context is a 128 byte binary. Anything you put on there will be padded with zero characters, to work around this I stuff the values with whitespace.
create function dbo.fn_user_name()
returns sysname
as
begin
declare #user sysname = rtrim(convert(nvarchar(64), context_info()))
if #user is null
return user_name()
return #user
end
go
Now you find replace all calls to user_name() in your code and replace them with this function.
Embed the context in your db calls in .net
There are 2 options here. Or you create your own SqlConnection class, or you create a factory method which will return an open sqlconnection like shown below. The factory method has as problem that every query you run will be 2 db calls. It is the least code to write though.
public SqlConnection CreateConnection(string connectionString, string user)
{
var conn = new SqlConnection(connectionString);
using (var cmd = new SqlCommand(
#"declare #a varbinary(128) = convert(varbinary(128), #user + replicate(N' ', 64 - len(#user)))
set context_info #a", conn))
{
cmd.Parameters.Add("#user", SqlDbType.NVarChar, 64).Value = user;
conn.Open();
cmd.ExecuteNonQuery();
}
return conn;
}
you would use this as:
using(var conn = CreateConnection(connectionString, user))
{
var cmd = new SqlCommand("select 1", conn);
return conn.ExecuteScalar()
}
For the alternate version of SqlConnection you will need to overload DbConnection and implement all methods of SqlConnection. The execute methods will prepend the query below and pass in the username as extra parameter.
declare #a varbinary(128) = convert(varbinary(128), #user + replicate(N' ', 64 - len(#user)))
set context_info #a
that class would then be used as:
using(var conn = new SqlContextInfoConnection(connectionString, user))
{
var cmd = new SqlCommand("select 1", conn);
conn.open;
return conn.ExecuteScalar()
}
I would personally implement option 2 as it would be closer to the way a normal SqlConnection works.
I know this is old, however this post is the only useful resource I've found, and I thought I'd share our solution that builds on Filip De Vos answer.
We also have a legacy VB6 app that utilises sp_setapprole (I appreciate this doesn't quite fit the OPs original post). Our .NET components that share the same database (and are essentially part of the application framework) are heavily based on Linq to SQL.
Setting the approle for a datacontext connection proved troublesome, considering the number of times a connection is opened and closed.
We ended up using writing a simple wrapper as suggested above. The only overridden methods are Open() and Close(), which is where the approle is set and unset.
Public Class ManagedConnection
Inherits Common.DbConnection
Private mCookie As Byte()
Private mcnConnection As SqlClient.SqlConnection
Public Sub New()
mcnConnection = New SqlClient.SqlConnection()
End Sub
Public Sub New(connectionString As String)
mcnConnection = New SqlClient.SqlConnection(connectionString)
End Sub
Public Sub New(connectionString As String, credential As SqlClient.SqlCredential)
mcnConnection = New SqlClient.SqlConnection(connectionString, credential)
End Sub
Public Overrides Property ConnectionString As String
Get
Return mcnConnection.ConnectionString
End Get
Set(value As String)
mcnConnection.ConnectionString = value
End Set
End Property
Public Overrides ReadOnly Property Database As String
Get
Return mcnConnection.Database
End Get
End Property
Public Overrides ReadOnly Property DataSource As String
Get
Return mcnConnection.DataSource
End Get
End Property
Public Overrides ReadOnly Property ServerVersion As String
Get
Return mcnConnection.ServerVersion
End Get
End Property
Public Overrides ReadOnly Property State As ConnectionState
Get
Return mcnConnection.State
End Get
End Property
Public Overrides Sub ChangeDatabase(databaseName As String)
mcnConnection.ChangeDatabase(databaseName)
End Sub
Public Overrides Sub Close()
Using cm As New SqlClient.SqlCommand("sp_unsetapprole")
cm.Connection = mcnConnection
cm.CommandType = CommandType.StoredProcedure
cm.Parameters.Add("#cookie", SqlDbType.VarBinary, 8000).Value = mCookie
cm.ExecuteNonQuery()
End Using
mcnConnection.Close()
End Sub
Public Overrides Sub Open()
mcnConnection.Open()
Using cm As New SqlClient.SqlCommand("sp_setapprole")
cm.Connection = mcnConnection
cm.CommandType = CommandType.StoredProcedure
cm.Parameters.Add("#rolename", SqlDbType.NVarChar, 128).Value = "UID"
cm.Parameters.Add("#password", SqlDbType.NVarChar, 128)Value = "PWD"
cm.Parameters.Add("#fCreateCookie", SqlDbType.Bit).Value = True
cm.Parameters.Add("#cookie", SqlDbType.VarBinary, 8000).Direction = ParameterDirection.InputOutput
cm.ExecuteNonQuery()
mCookie = cm.Parameters("#cookie").Value
End Using
End Sub
Protected Overrides Function BeginDbTransaction(isolationLevel As IsolationLevel) As DbTransaction
Return mcnConnection.BeginTransaction(isolationLevel)
End Function
Protected Overrides Function CreateDbCommand() As DbCommand
Return mcnConnection.CreateCommand()
End Function
End Class
Before:
Using dc As New SystemOptionDataContext(sConnectionString)
intOption= dc.GetIntegerValue("SomeDatabaseOption")
End Using
After:
Using dc As New SystemOptionDataContext(New ManagedConnection(strConnectionString))
intOption= dc.GetIntegerValue("SomeDatabaseOption")
End Using
Hope this helps others.

Resources