Am I missing something?
On the Npgsql documentation pages, I can't find the name of the assembly and the objects it provides.
Can someone point me in the right direction?
From some of the sample code, I know that one of the objects is called:
NpgsqlConnection
Thanks.
In Visual Studio add a reference to Npgsql to your project, then type F2 to open the "Object Browser" and you can see all the Npgsql classes and their methods.
I think that the Npgsql developers have tried to follow the .Net API (especially in Npgsql V3), so the Npgsql object model closely matches the .Net System.Data.Common object model with the "Db" part of the name changed to "Npgsql", so for instance the Npgsql equivalent of DbConnection is NpgsqlConnection.
I was a little confused when I started using Npgsql because it seems like it is not fully documented, but later I realized that is because it matches the .Net API so closely, you can refer to the .Net documentation directly.
Because Npgsql is so closely "ADO.Net Compliant", you can actually use the .Net interfaces in your code (the only thing specific to Npgsql in the code below is the New NpgsqlConnection call):
Public Sub Example()
Dim connection As IDbConnection = New NpgsqlConnection("connection string")
Using trans As IDbTransaction = connection.BeginTransaction
Dim command As IDbCommand = connection.CreateCommand
command.CommandText = "SELECT * FROM something;"
Using dr As IDataReader = command.ExecuteReader
While dr.Read
'do something
End While
End Using
End Using
End Sub
There are some differences, and those are documented at http://www.npgsql.org/doc/.
Related
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).
I've started working on a legacy code (i.e. no unit tests) Windows Forms app written in VB.Net and I've been asked to start introducing unit tests as I make changes. I have not done much unit testing before and I am unsure how to test a recurring pattern I see in the methods. Here is my attempt to outline a simplified typical example:
Private Sub cmdButton_Click(ByVal eventSender As Object, ByVal eventArgs As EventArgs) Handles cmdAprv.Click
'The event is Private and it then calls multiple other private methods
'but I will simplify drastically for this example:
If <conditions> Then
InsertEmployee()
End If
End Sub
Private Function InsertEmployee() As Integer
'Typically, the functions are quite long with lot of code initializing
'variables, but I will simplify drastically for this example:
Dim _name As String = "[]"
Dim _departmenmt As String = "Engineering"
Dim _salary As Double = 2000
'Then at the end there may be multiple database updates like this one:
Dim connectionString As String = "<Call a Function to get ConnectionString details>"
Using conn As New SqlConnection(connectionString)
Using cmd As New SqlCommand("INSERT INTO Employees (Name, Department, Salary) VALUES (#Name, #Department, #Salary)", conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("#Name", _name)
cmd.Parameters.AddWithValue("#City", _departmenmt)
cmd.Parameters.AddWithValue("#City", _salary)
conn.Open()
Dim i As Integer = cmd.ExecuteNonQuery()
conn.Close()
Return i
End Using
End Using
End Function
There is a lot of code in Private methods like this. To make these methods accessible to the testing project, I reckon I can downgrade the Function's accessibility protection from Private to Friend (VB.Net “Friend” = C# “internal” access modifier) and then use InternalsVisibleTo Attribute to mark the unit testing assembly as a friend assembly.
But I’m really not sure what to do with the Database INSERT or UPDATE code to make the function testable? One requirement I have is that the Unit Tests must not actually modify the database.
Can anyone show me a good example of refactoring a method like this for unit testing?
This is of course opinion-based. But here is what I do with legacy un-testable methods.
In your tested project, as you said, introduce InternalsVisibleTo
In your tested project introduce unit test - specific methods that will be only available for DEBUG configuration
#If DEBUG Then
Friend Function InsertEmployee_UT() As Integer
' call your method here
End Function
#End If
This is the principle. In fact, wrap your InternalVisibleTo with #If DEBUG Then
Build and perform your unit tests only in DEBUG configuration, and call the UT-functions that will not exist in RELEASE/Production code
Now Lets talk about breaking from the database. While calling DB can be a different sort of test, like Functional Test, you're right. Preferably, you can run your unit test without DB connection. What to do
Separate db calls into a single provider and pass Interface into the method. Yes, you need slight method change
Friend Function InsertEmployee(provider As IEmployeeData) As Integer
With this, in your unit test you can mock your provider and then examine. You can actually set this provider during construction or a property, then you don't even need to pass it to each method.
You can pass a callback As Function(Of . . ) or callback As Action(Of . . )
This way you also can separate functionality of retrieving data and calling for it.
These changes are not very intensive and can be done relatively quickly. And you will be able to do your testing. Changing private methods is safe, you can do it in any form or shape.
I have a WPF app that I'd like to change the connection string programmatically when the app loads. I use the Database-First approach for EF.
I spent a lot of time implementing various solutions found online including stack overflow and can't seem to get it to work.
The most common way seems to be to modify the Entity partial class. When I do this I get the following error at runtime:
Additional information: The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection. To learn more about Code First, Database First, and Model First see the Entity Framework documentation here: http://go.microsoft.com/fwlink/?LinkId=394715
I got the same error implementing various other ways as well. If someone could please help me implement a way to change the connection string at runtime I'd greatly appreciate it.
My current implementation is taken from this example solution:
Changing Databases at Run-time using Entity Framework
Implementation:
App.config containts the connection string and name
Partial class added with same name as Entity class:
Imports System.Data.Entity
Imports System.Data.EntityClient
Imports System.Data.SqlClient
Partial Public Class MyEntityName
Inherits DbContext
Public Sub New(ByVal connString As String)
MyBase.New(connString)
End Sub
End Class
In my Application.xaml code file I set a global string variable by calling a method that builds the EntityConnectionStringBuilder. This global string variable is then passed into an entity constructor.
Imports System.Reflection
Imports DevExpress.Xpf.Core
Imports System.Data.EntityClient
Class Application
Public Sub New()
entityConnStr = BuildConnectionString("[MyDataSource]", "[MyDatabase]")
End Sub
Private Function BuildConnectionString(ByVal DataSource As String, ByVal Database As String) As String
' Build the connection string from the provided datasource and database
Dim connString As String = "data source=" & DataSource & ";initial catalog=" & Database & ";persist security info=True;user id=[user];password=[password];trustservercertificate=True;MultipleActiveResultSets=True;App=EntityFramework""
' Build the MetaData... feel free to copy/paste it from the connection string in the config file.
Dim esb As New EntityConnectionStringBuilder()
esb.Metadata = "res://*/DB.[MyEntityName].csdl|res://*/DB.[MyEntityName].ssdl|res://*/DB.[MyEntityName].msl"
esb.Provider = "System.Data.SqlClient"
esb.ProviderConnectionString = connString
' Generate the full string and return it
Return esb.ToString()
End Function
Usage:
Using context = New MyEntity("entityConnStr")
Public connection variable string:
Public entityConnStr As String
I think you should remove the quotes when you pass the connection string to the constructor. You want to use the variable contents, not the variable name.
Use this:
Using context = New MyEntity(entityConnStr)
Instead of this:
Using context = New MyEntity("entityConnStr")
At the company I work for all applications pull information from that database, I have decided to write a detailed answer to answer how different databases can let the user know they have been altered. I will answer for the following types:
Access
SQL
Oracle
File systems (Files and folders)
Why I have done this?...... The company I work for have many different databases and applications that use these databases. However the applications spend a lot of time within the database checking to see if the data has been changed. I have complied this list to show how certain databases/files can use different tools to let an application know it has been changed. So an event can be fired off. This will hopefully reduce computing power and speed up the applications.
Please edit as you seem fit. If you need any other information a comment would be great. I am still in the process of adding the Oracle database solution and editing the Access and SQL.
Access and FileSystems/Files
For the access point I have used a SystemFileWatcher. This keeps an eye on the database and if it has been modified it will run the code to get the new data from the database. This means that the application is not constantly going in to the database and grabbing new data when it is not needed.
The FileSystemWatcher can run different code from the events such as name changed, moved or modified. I only need to use the modified. I have got the database path from an XML File I am using which means it is not hard coded and can be changed from the xml file and the watcher will watch else where.
Protected Overrides Sub OnStart(ByVal args() As String)
Dim g1 As New FileSystemWatcher()
g1.Path = GetSingleNode(XmlFileName, "data/G1Path")
g1.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)
g1.Filter = GetSingleNode(XmlFileName, "data/G1Filter")
AddHandler g1.Changed, AddressOf OnChanged
g1.EnableRaisingEvents = True
Dim g2 As New FileSystemWatcher()
g2.Path = GetSingleNode(XmlFileName, "data/G2Path")
g2.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)
g2.Filter = GetSingleNode(XmlFileName, "data/G2Filter")
AddHandler g2.Changed, AddressOf OnChanged
g2.EnableRaisingEvents = True
End Sub
Protected Overrides Sub OnStop()
End Sub
Public Shared Function GetSingleNode(ByVal xmlPath As String, ByVal nodeLocation As String) As String
Try
Dim xpathDoc As New XPathDocument(xmlPath) 'gets the nodes from the XML file ready to be put in to the network path/variables
Dim xmlNav As XPathNavigator = xpathDoc.CreateNavigator()
Return xmlNav.SelectSingleNode(nodeLocation).Value
Catch ex As Exception
Throw
End Try
End Function
After this I simply have an on changed function. Hope this helps anyone that needs it.
FileSystems/Files
For the file path and system paths the code above is very similar just using different paths and filters to get the certain types or names of files. This will then run the code if these have been changed/modified. If anybody would like code for this please write a comment and I can supply some.
SQL Databases
In the SQL databases there are multiple ways of checking to see if the data has been changed. I will reference a few MSDN Pages along with another question to provide information to these. However the way I used was slightly different as I didn't have a service broker running and no queues were enabled on my SQL databases.
Is there something like the FileSystemWatcher for Sql Server Tables?
http://msdn.microsoft.com/en-us/library/62xk7953.aspx#Y342
However the way I used was by using a checksum and a timer and checking the checksum on a loop to see if the database was changed. As the 'hash' always changes if the data is changed:
http://sqlserverplanet.com/design/how-to-detect-table-changes
http://www.mssqltips.com/sqlservertip/1023/checksum-functions-in-sql-server-2005/
My Code:
'Within main to get the first checksum value ready to be comapred with at a later date. These are global variables
Dim newdata As DataTable = SQLMethods.ExecuteReader(ConnectionString1, "SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM Alarms")
checksum = newdata.Rows(0).Item(0)
Timer1.Start()
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Timer1.Stop()
Dim newdata As DataTable = SQLMethods.ExecuteReader(ConnectionString1, "SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM Alarms")
checksumNew = newdata.Rows(0).Item(0)
If checksum <> checksumNew Then
MsgBox("Hello")
checksum = checksumNew
End If
Timer1.Start()
End Sub
As you can see if they do match the checksum is changed to match so the next time it happens they will be the same unless the database is indeed changed. I have stopped and then restarted the time to avoid confusion of the message box, however the message box is used for debugging purposes as an event could be fired here or what ever code was wanting to happen if the database was changed.
Oracle
After doing research I have not been able to implement this solution in my own application but hopefully it will provide info to other users. In Oracle there is something called OracleDependencyClass which provides an application a notification if the chosen data has been modified. I will supply some hyper-links that have some examples and the basics of how to use these in the hope someone doesn't need to mirror my own research.
Developing Applications with Database Change Notification
OracleDependency Class
Oracle® Data Provider for .NET Developer's Guide - OracleDependency Class(2)
Example of using the class in C# and VB.NET
If these pages don't help there are plenty of other webpages that you can access if you either search for "oracle dependency", "OracleDependency Class" and "Database Change Notification".
I am new here so forgive me if this is the wrong section for my question. My problem is that I can't populate a datgrid with the contents of a dataset. Having searched for the last few days to try and resolve this, I have given up and thought I would try here.
I am using Vs 2010 VB.Net and it's a WPF application
As you can tell from the code I am very new to this and any suggestions for improvement will be most welcome. I can see that the dataset is populated ok via the visualizer, I have a datagrid 'dgBOM' which I want to display the results. A popular solution in my searches was to add '.DataSource' but when I type the '.' after dgBOM the Datasource option is not there.
Any help would be much appreciated.
Thank you.
Code:
Public Sub Connect()
Dim cn As OleDbConnection
Dim cmd As OleDbCommand
Dim dr As OleDbDataReader
Dim ds As DataSet
Dim da As OleDbDataAdapter
Dim dt As DataTable
Dim drow As DataRow
Dim PartColumn As DataColumn
Dim CostColumn As DataColumn
dt = New DataTable("BOM")
ds = New DataSet("BOM")
PartColumn = New DataColumn("PartNo")
CostColumn = New DataColumn("Cost")
da = Nothing
cn = Nothing
dr = Nothing
Try
cn = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=\\Ls-wtgl834\share\Adrian\PriceLists\WAP-PriceLists.mdb;User ID=Admin")
cn.Open()
cmd = New OleDbCommand("select * from Inventory", cn)
dr = cmd.ExecuteReader
da = New OleDbDataAdapter(cmd)
dt.Columns.Add(PartColumn)
dt.Columns.Add(CostColumn)
While dr.Read()
If dr(0) = FBladeExtNo Then
FrontBladeCost = dr(1)
drow = dt.NewRow()
drow("PartNo") = FBladeExtNo
drow("Cost") = FrontBladeCost
dt.Rows.Add(drow)
ds.Tables.Add(dt)
Exit While
End If
End While
dgBOM.ItemsSource = ds
Catch
End Try
dr.Close()
cn.Close()
End Sub
I have given up on DataReader and all that. After writing a program a couple years ago where I had to provide all of the logic for change tracking and concurrency and relationship tracking and everything I threw up my hands because it is so time intensive.
Nowadays I use an O/RM framework; that is Object/Relation Mapping. Two of the biggies right now are Entity Framework (my personal favored framework) and NHibernate (originally written for Java but ported for .NET). These frameworks allow you to map database tables to .NET classes. Either ones you write yourself or ones generated by the tool (in Entity Frameworks case.
EF in Visual Studio 2010 allows you to do Model-First and Database-First development. Model-First allows you to create a diagram of how you want your classes to relate to each other (e.g. A Customer class that has a collection of Addresses, Phone Numbers and Events) then generates a database to store that data. Database-First is the opposite. You create your database, and EF tries to make a model that reflects the Database structure. It takes care of connection string creation, entity change tracking and concurrency, and it presents the data in nice objects that in my opinion are generated pretty darned fast. Personally I have found EFs data retrieval faster than my own hand executed data retrieval and object population.
WPF, with it's databinding capabilities, is geared more toward these dataobjects (here after I will just call them entities) than to DataReaders and DataAdapters. If you want to dive right in, here is a little Microsoft video on getting started with EF. Also be sure to check out WindowsClient.net as they have some good stuff there too.
Later on, once you get the hang of EntityFramework, check out the MVVM design pattern.