Connecting to a SQL server using ADODB from a C# dll - c#

I am writing a custom Connection class in C# for Excel to be able to connect to a SQL Server.
When I use SQLConnection from System.Data.SqlClient library I am able to establish a connection. The working code I've got:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Runtime.InteropServices;
namespace Test
{
[InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("6E8B9F68-FB6C-422F-9619-3BA6D5C24E84")]
public interface IConnection
{
bool Status { get; }
bool Open();
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("B280EAA4-CE11-43AD-BACD-723783BB3CF2")]
[ProgId("Test.Connection")]
public class Connection : IConnection
{
private bool status;
private SqlConnection conn;
private string connString = "Data Source=[server]; Initial Catalog=[initial]; User ID=[username]; Password=[password]";
public Connection()
{
}
public bool Status
{
get
{
return status;
}
}
public bool Open()
{
try
{
conn = new SqlConnection(connString);
conn.Open();
status = true;
return true;
}
catch(Exception e)
{
e.ToString();
return false;
}
}
}
}
And after adding the reference to Excel I am able to test the connection using a simple VBA code like this:
Sub TestConnection()
Dim conn As Test.Connection
Set conn = New Test.Connection
Debug.Print conn.Status
conn.Open
Debug.Print conn.Status
End Sub
It outputs:
False
True
So everything is fine. Now I would like to create custom Recordset class in my C# library so I decided to use an ADODB library and its RecordSetinstead of SqlDataReader as I am planning to work with some big chunks of data. So, I have modified my code to this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Runtime.InteropServices;
namespace Test
{
[InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("6E8B9F68-FB6C-422F-9619-3BA6D5C24E84")]
public interface IConnection
{
bool Status { get; }
bool Open();
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("B280EAA4-CE11-43AD-BACD-723783BB3CF2")]
[ProgId("Test.Connection")]
public class Connection : IConnection
{
private bool status;
private ADODB.Connection conn = new ADODB.Connection();
private string connString = "Data Source=[server]; Initial Catalog=[initial]; User ID=[username]; Password=[password]";
public Connection()
{
}
public bool Status
{
get
{
return status;
}
}
public bool Open()
{
try
{
conn.ConnectionString = connString;
conn.Open();
// conn.Open(connString, ["username"], ["password"], 0)
// what else can I try? is this where it actually fails?
status = true;
return true;
}
catch (Exception e)
{
e.ToString();
return false;
}
}
}
}
I also have added references to Microsoft ActiveX Data Objects 6.1 Library.
Now, when I am executing the VBA code it outputs:
0
0
But I was expecting 0 and 1. It seems to me like I am not properly connecting to the server ( credentials are the same i have just removed actual data from this code ).
I have tried to use different variations of the connection string, however it always returns 0 and 0. I have tried creating a new project with new GUIDs and also tried renaming the projects, classes, etc. nothing has worked. I am suspecting its the establishment of the connection but I am unsure how to debug a dll.
I have used link1, link2, link3, link4 for reference
Update:
I have wrote the exception to the file as TheKingDave suggested. This is the exception error message
System.Runtime.InteropServices.COMException (0x80004005):
[Microsoft][ODBC Driver Manager] Data source name not found and no
default driver specified at ADODB._Connection.Open(String
ConnectionString, String UserID, String Password, Int32 Options) at
TestADODB.Connection.Open() in c:\Users\administrator\Documents\Visual
Studio 2012\Projects\Test\Test\Connection.cs:line 49

The connection string is missing Provider=SQLOLEDB.
The ADODB.Connection needs to know what type of database it is connecting to.

Related

How to use MongoDB connection globally

My API is on .net mvc c# platform. I am using mongo DB to drop and store data the following way. It is not working properly when I try to drop and insert data concurrently. The connections are multiplying and the requests are not executed in the same order. How can I use the MongoDB in a global class with only one connection open? do give some reference to look into.
public static string DB= DBConnection.MongoDB;
public bool Insert(Data data)
{
try
{
var con = new MongoClient(DBConnection.ConnectionString);
var db = con.GetDatabase(DB);
db.InsertOne(data);
return true;
}
catch (Exception exception)
{
}
}
using System.Configuration;
namespace DataAccess.Implementations
{
internal class DBConnection
{
#region ConnectionString
public static string ConnectionString { get { return ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString; } }
#endregion
#region Database
public static string MongoDB{ get { return ConfigurationManager.AppSettings["MongoDB"].ToString(); } }
#endregion
}
}
Try using a Singleton pattern:
https://social.msdn.microsoft.com/Forums/en-US/9e152212-2109-4d07-adbf-4ff0326c077b/how-to-establish-db-connection-using-singleton-pattern?forum=csharpgeneral
Singleton design pattern is preferred to get a DB Connection

Trouble mocking SqlConnection for Unit Tests

I am calling code that I cannot change that takes in a SqlConnection and a Transaction created from that SqlConnection. I am attempting to mock this SqlConnection using Moq 4.16.1. I am getting the following error when attempting to unit test the code:
Unable to cast object of type 'Castle.Proxies.IDbConnectionProxy' to type 'System.Data.SqlClient.SqlConnection'.
I have wrapped the SqlConnection in my own wrapper to try to get this to work, but this has not helped.
SqlConnectionWrapper:
using System.Data;
using System.Data.SqlClient;
namespace Wrappers
{
public class SQLConnectionWrapper : ISQLConnectionWrapper
{
public string ConnectionString { get; private set; }
public SQLConnectionWrapper(string connectionString)
{
ConnectionString = connectionString;
}
public IDbConnection Open()
{
return new SqlConnection(ConnectionString);
}
}
}
Unit test:
private Mock<ISQLConnectionWrapper> _mockSqlConnectionWrapper;
[SetUp]
public void Setup()
{
_mockSqlConnectionWrapper = new Mock<ISQLConnectionWrapper>();
var mockSQLConnection = new Mock<IDbConnection>();
mockSQLConnection.SetupAllProperties();
_mockSqlConnectionWrapper.Setup(x => x.Open())
.Returns(mockSQLConnection.Object);
}
Any help with this would be greatly appreciated.

Strange behavior creating a new Database with Npgsql and Entity Framework

I'm trying to create a new database with npgsql and EF 6. This is my code:
using System.Data.Common;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Migrations;
using System.Data.Entity;
using System.Data.Entity.Migrations.Sql;
using Npgsql;
using NUnit.Framework;
namespace EntityFramework.PostgreSql.Test.IntegrationTests
{
[TestFixture]
public class PostgreSqlMigrationSqlGeneretorHistoryTest
{
private const string ConnectionString = "Server=127.0.0.1;Port=5432;Database=testEF6;User Id=postgres;Password=p0o9i8u7y6;CommandTimeout=20;Preload Reader = true;";
private const string ProviderName = "Npgsql";
[Test]
public void CreateNewDatabase()
{
const string cs = "Server=127.0.0.1;Port=5432;Database=testEFxx;User Id=postgres;Password=p0o9i8u7y6;CommandTimeout=20;Preload Reader = true;";
var db = new LocalPgContext(cs);
if (!db.Database.Exists())
db.Database.Create();
var exists = db.Database.Exists();
db.Database.Delete();
Assert.IsTrue(exists);
}
public class LocalPgContext : DbContext, IDbProviderFactoryResolver, IDbConnectionFactory
{
public LocalPgContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
Database.SetInitializer(new CreateDatabaseIfNotExists<LocalPgContext>());
}
public DbProviderFactory ResolveProviderFactory(DbConnection connection)
{
return DbProviderFactories.GetFactory("Npgsql");
}
public DbConnection CreateConnection(string nameOrConnectionString)
{
return new NpgsqlConnection(nameOrConnectionString);
}
DbConnection IDbConnectionFactory.CreateConnection(string nameOrConnectionString)
{
return CreateConnection(nameOrConnectionString);
}
DbProviderFactory IDbProviderFactoryResolver.ResolveProviderFactory(DbConnection connection)
{
return new LocalPgProviderFactory();
}
}
public class LocalPgProviderFactory : DbProviderFactory
{
public override DbConnectionStringBuilder CreateConnectionStringBuilder()
{
return new NpgsqlConnectionStringBuilder(ConnectionString);
}
public override DbConnection CreateConnection()
{
return new NpgsqlConnection(ConnectionString);
}
}
}
}
The strange thing is that I create a new connection using Npgsql but when I'm executing if (!db.Database.Exists()) it try to create a connection using SqlServer provider. It tell me that it doesn't know the "port" attribute of the connection string because sql server haven't this attribute.
I'm thinking that it is looking for the default provider factory into the web.config file but not finding it, it set sql server as default provider.
I would like to set Npgsql as default provider without using a config file at all.
Npgsql add the support to delete or create the database from the 2.2.0 version (now is in beta 1)

Project Server Console Application Error: The type name 'LoginWindows' does not exist in the type 'ProjectServer.WebSvcLoginWindows'

I can't figure out how to get rid of this error. I'm very new to C#, but please give any assistance you can. Thanks
Error: The type name 'LoginWindows' does not exist in the type 'ProjectServer.WebSvcLoginWindows'
Source Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Configuration;
using ProjectServer.LoginForms;
using ProjectServer.Statusing;
using ProjectServer;
using System.Net;
using System.Threading;
using PSLibrary = Microsoft.Office.Project.Server.Library;
using System.Windows.Forms.MessageBox;
using System.Windows.Forms;
namespace ProjectServer
{
public partial class LogonProjectServer : Form
{
public static WebSvcLoginWindows.LoginWindows loginWindows =
new WebSvcLoginWindows.LoginWindows();
public static CookieContainer cookies = new CookieContainer();
public static WebSvcProject.LoginForms loginForms =
new SyprisProjectServer.WebSvcProject.LoginForms();
private const string LOGINFORMSWEBSERVICE = "/PWA/_vti_bin/PSI/LoginForms.asmx?wsdl";
private const string LOGINWINDOWSWEBSERVICE = "/PWA/_vti_bin/PSI/LoginWindows.asmx?wsdl";
private string baseUrl; // Example: http://ServerName/ProjectServer/
public bool LogonPS(bool useWinLogon, string baseUrl,
string userName, string password)
{
const string LOGINWINDOWS = "PWA/_vti_bin/PSI/LoginWindows.asmx?wsdl";
const string LOGINFORMS = "PWA/_vti_bin/PSI/LoginForms.asmx?wsdl";
bool logonSucceeded = false;
try
{
if (useWinLogon)
{
loginWindows.Url = baseUrl + LOGINWINDOWS;
loginWindows.Credentials = CredentialCache.DefaultCredentials;
if (loginWindows.Login()) logonSucceeded = true;
}
}
// Catch statements
catch (System.Web.Services.Protocols.SoapException ex)
{
MessageBox.Show(ex.Message.ToString(), "Logon Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (System.Net.WebException ex)
{
MessageBox.Show(ex.Message.ToString(), "Logon Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return logonSucceeded;
}
}
}
The problem is likely due to either the class name (LoginWindows) or the namespace (WebSvcLoginWindows) being incorrect when you create the loginWindows variable:
public static WebSvcLoginWindows.LoginWindows loginWindows = new WebSvcLoginWindows.LoginWindows();
Make sure the namespace and class name are spelled correctly and have the correct capitalisation.
If the class is contained in a separate asssembly, make sure your winforms project has a reference to the other assembly.
Hope that helps.
Check your build configuration and make sure all referenced projects are being built and being built for the correct configuration (64 vs 32 bit). Also, ensure you are using the correct version of any referenced dlls.

Invalid authorization specification and Invalid connection string attribute

I am getting the following error "Invalid authorization specification, Invalid connection string attribute"
//namespaces
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Configuration;
using System.IO;
using System.Data.OleDb;
namespace Database1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public bool IsValidConnectionForPrinting()
{
//string declaration
string str = #" Provider = SQLOLEDB; Data Source = sekhar; Database = DMS; UserId = sa; Password = 123";
//Oledbconnection to database
OleDbConnection oleDbcon = new OleDbConnection(str);
try
{
oleDbcon.Open();
MessageBox.Show("hai");
oleDbcon.Close();
}
//Exception
catch (Exception ex)
{
if (ex.Message.StartsWith("Invalid object name"))
{
MessageBox.Show(ex.Message.Replace("Invalid object name", "Table or view not found"), "Connection Test");
}
//Connection
private void btnConnTest_Click(object sender, EventArgs e)
{
if (IsValidConnectionForPrinting())
{
MessageBox.Show("Connection succeeded", "Connection Test");
}
}
}
}
I would recommend using a connection string that does not include Database or Initial Catalog, and then calling something like:
oleDbcon.ChangeDatabase("DMS");
This is because, as you have already experienced, different database drivers use different syntax for referring to the database in the connection string.
I had this error and it turned out the code path had not connected to the database.
Worth checking.

Categories