Get database list in Npgsql - c#

How can I get a list of all available PostgreSQL databases on a user's computer using Npgsql in C#?

In postgreSQL there are two way to do it :
\l
SELECT datname FROM pg_database;

Using Npgsql You can use such code snippet:
IEnumerable<string> GetDatabaseNames()
{
var connStrBuilder = new NpgsqlConnectionStringBuilder();
connStrBuilder.Host = "localhost";
connStrBuilder.Username = "theduck";
connStrBuilder.Password = "password123";
connStrBuilder.Database = "postgres"; // this database is always present
using (var conn = new NpgsqlConnection(connStrBuilder.ConnectionString))
{
conn.Open();
using (var command = new NpgsqlCommand("SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname;", conn))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
yield return reader.GetString(0);
}
}
}
}

Related

Fastest way to get multiple rows using npgsql

I have a following code with List of guids and I need to get all corresponding items from database:
var guids = new List<string>()
{
"1HFAoQchL1NB9Tc5wJLYHm",
"1OLd2nLP92c87kmkHaMAtO",
"2FwmMnAX98sg537nfo$S39",
"38pd0XqUvEvA8nrnF$3vvZ",
"0iqYqWKBvC_x62wk0jcKW3",
"0njEfI2BzDEeQpiOo5S18q",
"0chMA4Bgf9nxnq2i1gG9Fb",
"3TrnV9L79FfBz0ni6_bJ9N"
};
foreach (var gd in guids)
{
MemoryStream stream = null;
using (var conn = new NpgsqlConnection(connectionString))
{
string sQL = $"SELECT geometricaldata FROM entities WHERE guid= '{gd}'";
using (var command = new NpgsqlCommand(sQL, conn))
{
conn.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
stream = new MemoryStream((byte[])reader[0]);
}
reader.Close();
}
}
}
}
Do I really need to do this in a loop one by one or it would be better to batch SELECT statements? Or maybe there is another way how to get multiple rows with one query that I don't know of?

Automapper to read single record

I have been trying to read single Record using AutoMapper. But I couldn't get through using the below code,
public ChartOfAccount GetSingleCOA( )
{
string queryString = "select * from ChartofAccounts where AccNo=423";
using (var connection = new SqlConnection(conStr))
using (var command = new SqlCommand(queryString, connection))
{
connection.Open();
using (var reader = command.ExecuteReader())
if (reader.HasRows)
{
reader.Read();
return Mapper.Map<IDataRecord, ChartOfAccount>(reader);
}
}
return null;
}
simply changing the line to
return Mapper.DynamicMap<IDataReader, ChartOfAccount>(reader);
solved the issue

SQLite keeps locking my database when doing SELECT + UPDATE (C#)

I am trying to doing this:
Read a row from an SQLite db (in GetRuleByID() method)
Update the same row that I just read during (1) (See UpdateStatusForRuleID() method)
However my problem is that SQLite locks the database after the SELECT in GetRuleByID() so that update in UpdateStatusForRuleID() is only successful when called the first time.
I have tried enabling Write-Ahead-Logging in SQLite as well as PRAGMA read_uncommitted=1 in order to avoid SQLite locking the database for the SELECT, but this does not appear to work.
This should be simple but I have so far spent a complete night trying to solve this... Please help !
private static MicroRuleEngine.Rule GetRuleByID(int ruleID, SQLiteConnection connection, out Dictionary<string, string> dict)
{
dict = new Dictionary<string, string>();
string sql = String.Format("select * from rules WHERE ID = {0} ", ruleID.ToString());
SQLiteCommand command = new SQLiteCommand(sql, connection);
SQLiteDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
// Convert row into a dictionary
for (int lp = 0; lp < reader.FieldCount; lp++)
{
dict.Add(reader.GetName(lp), reader.GetValue(lp) as string);
}
string json = dict["fulljson"];
MicroRuleEngine.Rule r = Newtonsoft.Json.JsonConvert.DeserializeObject<MicroRuleEngine.Rule>(json);
//command.Dispose();
return r;
}
}
internal static void UpdateStatusForRuleID(SQLConnectionManager DBMANAGER, int ruleID, bool status)
{
Dictionary<string, string> dict = null;
string dbVal = (status) ? "1" : "0";
MicroRuleEngine.Rule r = null;
string newJSON = null;
using (SQLiteConnection connection = DBMANAGER.CreateConnection())
{
r = GetRuleByID(ruleID, connection, out dict);
r.Active = (status);
newJSON = Newtonsoft.Json.JsonConvert.SerializeObject(r);
Thread.Sleep(1000);
string sql = "UPDATE rules SET active = #a, fulljson=#j WHERE ID = #i";
using (var command = new SQLiteCommand(sql, connection))
{
command.Parameters.Add(new SQLiteParameter("#a", dbVal));
command.Parameters.Add(new SQLiteParameter("#i", ruleID));
command.Parameters.Add(new SQLiteParameter("#j", newJSON));
command.ExecuteNonQuery(); // Database is locked here ???
}
connection.Close();
}
}
"Database is locked" means that some other connection (in the same or some other process) still has an active transaction.
You don't need multiple connections (unless you are using multiple threads); just use a single connection object for all database accesses.
Ensure that all command, reader, and transaction objects (and connections, if you decide to use temporary ones) are properly cleaned up, by using using:
using (var command = new SQLiteCommand(sql, connection))
using (var reader = command.ExecuteReader())
{
if (reader.HasRows)
...
}
Apparently, the code below works. I basically dropped the GetRuleByID() method (but then I had to re-write 4 other methods)
Thanks to all who provided input.
internal static void UpdateStatusForRuleID(SQLConnectionManager DBMANAGER, int ruleID, bool status)
{
string dbVal = (status) ? "1" : "0";
MicroRuleEngine.Rule r = null;
string newJSON = null;
using (SQLiteConnection conn = DBMANAGER.CreateConnection())
{
string sql = String.Format("select * from rules WHERE ID = {0} ", ruleID.ToString());
using (var command = new SQLiteCommand(sql, conn))
using (var reader = command.ExecuteReader())
{
if (reader.HasRows)
{
reader.Read();
string json = reader["fulljson"].ToString();
r = Newtonsoft.Json.JsonConvert.DeserializeObject<MicroRuleEngine.Rule>(json);
r.Active = (status);
newJSON = Newtonsoft.Json.JsonConvert.SerializeObject(r);
string sql2 = "UPDATE rules SET active = #a, fulljson=#j WHERE ID = #i";
using (var command2 = new SQLiteCommand(sql2, conn))
{
command2.Parameters.Add(new SQLiteParameter("#a", dbVal));
command2.Parameters.Add(new SQLiteParameter("#i", ruleID));
command2.Parameters.Add(new SQLiteParameter("#j", newJSON));
command2.ExecuteNonQuery();
}
}
}
}
}

ASP.NET Core 1 RC2 - database schema

Can somebody advise how to get the schema in ASP.NET Core 1 RC2?
using (SqlConnection connection = new SqlConnection("Server=.;Database=Mydb;Trusted_Connection=True;MultipleActiveResultSets=true"))
{
connection.Open();
connection.GetSchema("Tables"); // doesn't work
}
The connection.GetSchema has been depreciated in Asp.Net Core due as it returns the DataTable which has also been depreciated. The way to do this now is is to open run the ExecuteReader() function, and then use the GetSchemaColumn() function from the resulting reader object.
Here is a sample:
public static void Main(string[] args)
{
using (SqlConnection connection = new SqlConnection("Server=(localdb)\\v11.0;Database=MyAdventureWorks;Trusted_Connection=True"))
{
connection.Open();
SqlCommand cmd = new SqlCommand("select * from [Person].[Person]", connection);
DbDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.SchemaOnly);
if (reader.CanGetColumnSchema())
{
var columns = reader.GetColumnSchema();
foreach (var column in columns)
{
Console.Write("ColumName: " + column.ColumnName);
Console.Write(", DataTypeName: " + column.DataTypeName);
Console.Write(", ColumnSize: " + column.ColumnSize);
Console.WriteLine(", IsUnique: " + column.IsUnique);
}
}
else
throw new Exception("Connection does not support GetColumnSchema.");
}
Console.ReadLine();
}
Note: I think this is still be stabalized in Rc2. For example the column.IsKey function always returning null.
If you need all table names from a database I managed to do this:
public List<string> getTables()
{
List<string> result = new List<string>();
using (SqlConnection connection = new SqlConnection(appSettings.ConnectionStringSamples))
{
connection.Open();
using (SqlCommand command = new SqlCommand("SELECT name FROM sys.Tables;", connection))
using (SqlDataReader reader = command.ExecuteReader())
while (reader.Read()) result.Add(reader["name"].ToString());
}
return result;
}

How can I populate a list with values from a SQL Server database?

The list will grow and shrink depending on how many items I have in my database.
I need to populate a list not a listbox. I understand I will need to open a connection.
using (var conn = new SqlConnection(Properties.Settings.Default.DBConnectionString))
{
using (var cmd = conn.CreateCommand())
{
conn.Open();
List<string> TagList = new List<string>();
for (int i = 0; i < TagList.Count; i++)
TagList[i].Add("Data from database");
cmd.ExecuteNonQuery();
}
}
I'm really not sure how to do this and I'm sure my method up here looks very wrong so I really need help.
Could someone show me what I'm doing wrong?
public IEnumerable<string> GetTagList()
{
using (var connection = new SqlConnection(Properties.Settings.Default.DBConnectionString))
using (var cmd = connection.CreateCommand())
{
connection.Open();
cmd.CommandText = "select Tag from TagsTable"; // update select command accordingly
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
yield return reader.GetString(reader.GetOrdinal("Tag"));
}
}
}
}
then you can call it as below
List<string> tags = GetTagList().ToList();
I would like to share my solution, hope helps someone in the future:
public List<string> getFromDataBase()
{
List<string> result = new List<string>();
using(SqlConnection con = new SqlConnection("connectionString"))
{
con.Open();
DataTable tap = new DataTable();
new SqlDataAdapter(query, con).Fill(tap);
result = tap.Rows.OfType<DataRow>().Select(dr => dr.Field<string>("columnName")).ToList();
}
return result;
}
This would do as it is (if I didn't do any typos...)
private void LoadList()
{
List<string> tagsList = new List<string>();
using (IDbConnection connection = new SqlConnection(Properties.Settings.Default.DBConnectionString))
{
connection.Open();
using (IDbCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT TAGCOLUMN FROM TAGSTABLE";
using (IDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
if (!reader.IsDBNull(0))
tagsList.Add(reader.GetString(0));
}
reader.Close();
}
}
connection.Close();
}
}
EDIT:
Of course you have to change the select statement to the correct one from your database.
I just used a pseudo one to show you what to put there.

Categories