Here I need to get a string that identifies the database client using PostgreSQL with C#. Here is the following example.
Example:
private static void OpenNpgsqlConnection(string connectionString)
{
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
{
connection.Open();
Console.WriteLine("WorkstationId: {0}", connection.WorkstationId);
}
}
Error:
'Npgsql.NpgsqlConnection' does not contain a definition for 'Workstationid'.
You seem to mean the MS SQL specific property WorkstationId of SQLConnection.
This is an MS SQL specific property. It does not exist for nPgSQL, though of course you could add it.
The documentation in MSDN is profoundly useless, so it's hard to tell what it's actually for. At a wild guess, I think you probably mean something like PostgreSQL's application_name - a way for the server to find out information about the client from within a stored procedure or function.
client drivers or applications have to set application_name; there's nothing that gets set automatically to the "network name". (What would that even mean if the client was not a Windows box?). Your application could set application_name, either in the connection string or via an explicit SET command.
You can also run arbitrary SET commands. E.g you might decide to store the "workstation name" in the myapp.workstationid connection property. So you:
SET myapp.workstationid = 'BOBSCOMPUTER';
from your app, after making the initial connection.
Stored procedures can now access it with current_setting('myapp.workstationid').
Note that in both cases, a user with the ability to send raw SQL can just replace these settings with whatever they want. So don't use them for security.
Related
I am new to working with databases.I am using postgres database.I want to connect it to c# for my project.Since I have multiple form screen in my project, I assume it is better to create a seperate database connection class instead of using the same code in every other classes.I want to learn how to create an effective postgres database connection class in c#
There's no need to create a connection class since database connections and commands aren't complicated or expensive to create. The best practice is to create a connection and command, execute the SQL, and then dispose of both of them. The typical pattern is:
string connString = {connection string from config};
using (OdbcConnection conn = new OdbcConnection(connString)) {
using(OdbcCommand cmd = new OdbcCommand(sql, conn) {
// execute command
}
}
The using construct ensures that the connection and command are closed een if there is a database error.
Take a look at this website: https://www.connectionstrings.com/postgresql/
This is a great resource for finding connection strings to a variety of different databases! I reference it quite a bit. There are a couple of different connection strings for postgreSql, so you will need to dtermine which one is best to use for your use case.
I wouldn't set up a special class for a connection. Instead I recommend that you use an appsettings.json or web.config file to store the connection string and call it when you need it. Check out the documentation from Microsoft: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0
Asked this question a few days ago but maybe wasn't too specific.
Basically, I'm writing a console app that accepts a list of stored procedure names and arbitrarily executes them. The app is supposed to log to Slack, etc. on the progress of these sprocs, as well as do some other stuff later.
The 'other stuff' I mentioned interacts with known database models, and since we have a library of ServiceStack/OrmLite types build up, I am using OrmLite to interact with the database later.
So, since I have OrmLite included and configured in the project, I'm just using the OrmLite IDbConnection to execute the stored procedures, even if it's just by name. The sprocs simply move data to another database, one that the app doesn't need to interact with -- so I'm not SELECTing any data into the app with the sprocs and there's no POCO representation of what's moved.
However, the sprocs spit out a number of informational PRINT statements that I want to capture and log to our team in a formatted manner via Slack. Enabling full-on debug logging spits out a little too much information for this purpose.
Is there any way I can configure the Ormlite SqlServerDialect.Provider, the IDataReader, etc. to basically capture the SqlConnection.InfoMessage
event (or to provide it with a connection already prepped with a SqlInfoMessageEventHandler)?
The logging strategy approach for doing this is to configure a filter in your logging provider to only log the messages you're interested in.
OrmLite's SQL debug logging messages containing the SQL and DB Params are logged under the ServiceStack.OrmLite.OrmLiteResultsFilterExtensions Type.
To make this scenario easier I've just added new OrmLiteConfig.BeforeExecFilter and OrmLiteConfig.AfterExecFilter which you can use to execute custom logic before and after a DB Command is executed, e.g:
OrmLiteConfig.BeforeExecFilter = dbCmd => Console.WriteLine(dbCmd.GetDebugString());
This change is available from v5.0.3 that's now available on MyGet.
Update:
Looking through the ServiceStack.OrmLite source, it looks like IDbConnection can be cast to SqlConnection using (SqlConnection)IDbConnection.ToDbConnetion().
Wrapping this up in an OrmLiteExecFilter to be called on every statement, casting the IDbConnection and creating the DbCommand with the cast connection worked for me:
public class LogInfoMessageFilter : OrmLiteExecFilter
{
ILog SlackLog = LogManager.GetLogger("SlackLogger");
public override T Exec<T>(IDbConnection dbConn, Func<IDbCommand, T> filter)
{
var holdProvider = OrmLiteConfig.DialectProvider;
// casting, skipping type checks for brevity
var sqlConn = (SqlConnection)dbConn.ToDbConnection();
// add the event
sqlConn.InfoMessage += _HandleInfoMessage;
var dbCmd = CreateCommand(sqlConn);
try
{
return filter(dbCmd);
}
finally
{
DisposeCommand(dbCmd, sqlConn);
OrmLiteConfig.DialectProvider = holdProvider;
}
}
private void _HandleInfoMessage(object sender, SqlInfoMessageEventArgs args)
{
SlackLog.Info($"what does the sproc say? {args.Message}");
}
}
// before opening the connection:
OrmLiteConfig.ExecFilter = new LogInfoMessageFilter();
However, now that #mythz has replied with an 'official' way to do this, I'll go about refactoring. Just thought I'd plop this here in case it suits anyone's use case.
I am testing various DB connection methods in C#. In particular, I am testing SqlConnection and OdbcConnection classes; my DB is SQLServer Express (.\SQLEXPRESS). Both are working reasonably well, except in listing available databases on the server.
In my test code I use a "generic" DbConnection object and a simple factory to create an instance of specific SqlConnetion and OdbcConnetion subclasses (they both derive from DbConnection):
DbConnection connection;
switch (connection_type)
{
case DbConnectionType.DBCONN_MSSQL:
connection = new SqlConnection(...sql connection string...);
break;
case DbConnectionType.DBCONN_ODBC:
connection = new OdbcConnection(...odbc connection string...);
break;
}
The trick seems to work well except when I try to get the list of databases on the server:
DataTable databases = connection.GetSchema("Databases");
foreach (DataRow database in databases.Rows)
{
String databaseName = database["database_name"] as String;
Console.WriteLine(databaseName);
}
When "connection" is an OdbcConnection (and, note, the database is the same), I get an exception saying that "Databases" key was not found. I listed all the keys exposed by GetSchema(), and the ODBC version returns only a subset of the items exposed by the SQLServer version. I couldn't find any hint about this specific problem. Is it a documented/expected behaviour? Am I doing something wrong?
NOTE: here how I build the ODBC connection string:
OdbcConnectionStringBuilder builder;
builder = new OdbcConnectionStringBuilder();
builder.Driver = "SQL Server";
builder.Add("Server", ".\\SQLEXPRESS");
builder.Add("Uid", "");
builder.Add("Pwd", ""); // Using current user
builder.Add("Integrated Security", "SSPI");
connection = new OdbcConnection(builder.ConnectionString);
Is it a documented/expected behaviour?
Yes. See Retrieving Database Schema Information
Am I doing something wrong?
If your goal is to read SQL Server metadata in a provider-agnostic way, then yes. You should query the SQL Server catalog views directly. sys.databases, sys.tables, etc.
Make sure your "Databases" model has a valid Key. Add the [Key] Data annotation if the key you want to implement for that database doesn't follow the "ClassName"+"ID" entity framework rule.
I found a solution that must be for a older version then vs2010. I would like to know how to do this for vs2010? Does anyone know?
http://www.csharpbydesign.com/2008/01/overriding-dataset-settings-co.html
Let me explain little more detail.
I have a c# generated dataset. How can I change the connection string so I can use the dataset with another (identically structured yet differently populated) database? This has to occur at runtime as I do not know the server or database name at compile time. i AM USING vs2010 and SQL Server 2008 R2 Express
I think there is no simple way and you cannot change the Connection-String programmatically for the entire DataSet since it's set for every TableAdapter.
You need to use/create the partial class of the TableAdapter to change the connection-string since the Connection property is internal (if your DAL is in a different assembly). Don't change the designer.cs file since it will be recreated automatically after the next change on the designer. To create it just right-click the DataSet and chose "show code".
For example (assuming the TableAdapter is named ProductTableAdapter):
namespace WindowsFormsApplication1.DataSet1TableAdapters
{
public partial class ProductTableAdapter
{
public string ConnectionString {
get { return Connection.ConnectionString; }
set { Connection.ConnectionString = value; }
}
}
}
Now you can change it easily:
var productTableAdapter = new DataSet1TableAdapters.ProductTableAdapter();
productTableAdapter.ConnectionString = someOtherConnectionString;
Here's a screesnhot of my sample DataSet and the created file DataSet1.cs:
There's actually a much easier way to change the connection string.
Go to the Settings screen, where the connection string is displayed as a connection string.
First mark and copy the connection string that's displayed.
Then change the type from connection string to string. The text for the string will change to include xml.
Then paste the copied connection string over the xml text.
Then change the scope from Application to User.
When I want to change the connection string, I use the following code.
// assign the path to use to the variable fullpath (or whatever)
string newConnection = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}", fullpath);
Properties.Settings.Default.HootConnectionString = newConnection;
Properties.Settings.Default.Save();
In my case, I have a global Dataset active, so I have to make that the data is reread by the tableadapter. And, of course, you'll have to add error control to make sure the database is still there.
You'll notice that this will not change what is displayed in Application Settings. Those are defaults.
This works for an Access database; so your mileage and requirements may vary.
EDIT: Caveat. As it works out, when installed, the connection string works well for opening and reading database content, but it complains about not having a connection string when trying to update a database.
I am using an ASP.Net and C# front end to run some reports. I want to open an SQL Connection to the data source used by the report.
When the report uses integrated security it is easy enough to create a connection, however I want to create a connection when the user name and password are stored by the reporting server.
I can get SQL Server path and initial catalogue, using
DataSource[] dataSources;
DataSourceReference dsReference;
DataSourceDefinition dsDefinition;
string dsPath;
ReportingService2005 rs = new ReportingService2005();
dataSources = rs.GetItemDataSources(reportPath);
if (dataSources.Length > 0)
{
dsReference = (DataSourceReference)dataSources[0].Item;
dsPath = dsReference.Reference;
dsDefinition = rs.GetDataSourceContents(dsPath);
// ....
}
I can also get the user name using
username = dsDefinition.UserName;
however if I use
password = dsDefinition.Password;
password = null, and can't be used to open the Sql Connection.
Is there a way to create an SQLConnection that uses the connection string and username and password credentials of a data source?
I am using Reporting Services 2008, and .NET 3.5 with web references to ReportService2005.asmx and ReportExecution2005.asmx
I really don't think it's possible, as this would pretty much constitute a security hole. I know this isn't the answer you are looking for, but I would parameterise the location of your reports (i.e. the IP/name of your MSRS server) and store them in your web.config along with a matching SQL instance. While it's not exactly what you're after, I think that's about as close as you are going to get.
I think you should read this page:
http://msdn.microsoft.com/en-us/library/reportservice2005.datasourcedefinition_properties.aspx
it shows the password field is write-only, so you can't set its value,but read it only.