C# LINQ for Npgsql - c#

I have been searching the internet extensively and have found no clear path for using LINQ queries on Npgsql Objects. I want to get away from using the laborious:
using (var connection = new NpgsqlConnection(ConnectionString))
{
using (var adapter = new NpgsqlDataAdapter(query, connection))
{
connection.Open();
var command = adapter.SelectCommand;
command.Parameters.Add(param1);
command.Parameters.Add(param2);
var dataSet = new DataSet();
adapter.Fill(dataSet);
//... Do something with the dataset
}
}
I would love it if I could do something LINQ-esque like:
var pendingBalances = from c in customers
where c.Balance > 100
select new { c.FirstName, c.LastName };
Not only is it easier/shorter to write, it is way easier to read for debugging and helping future developers who have to read it.
Please tell me this is possible? If so, what object do I use in the place of "customers" to run the query against? It needs to be some sort of DbContext right? Thanks for the help!

You should use EF Core or EF 6 ORM that have Npgsql providers.
Here's a link

Related

Can Entity Framework Core run non-query calls?

Unfortunately my EF application has to call stored procedures I am unable to change. While this is not ideal I can normally get around it. However, I have a stored proc that does return anything. How does EF core deal with this? I know in previous versions you could run ExecuteNonQuery but I haven't been able to find anything similar in EF Core.
I normally run my queries through a helper as such, where T is a class that maps to a return type EF can serialize to:
context.Set<T>()
.AsNoTracking()
.FromSql(query, args)
.ToListAsync();
However it looks like Set always requires a type as does .Query. Nothing else I've seen off of context would allow you to make a non-queryable call. Am I missing something?
I am using Microsoft.EntityFrameworkCore: 1.2.0
You can use the DbContext.DatabaseExecuteSqlCommand method
using(var context = new SampleContext())
{
var commandText = "INSERT Categories (CategoryName) VALUES (#CategoryName)";
var name = new SqlParameter("#CategoryName", "Test");
context.Database.ExecuteSqlCommand(commandText, name);
}
Or you can revert to ADO.NET calls off the Context:
using (var context = new SampleContext())
using (var command = context.Database.GetDbConnection().CreateCommand())
{
command.CommandText = "DELETE From Table1";
context.Database.OpenConnection();
command.ExecuteNonQuery();
}

Backup SQL Server Schema With Data

I've been tasked with creating a backup of the data in our "default schema" database dbo to the same database using a new schema called dbobackup.
I honestly do not understand what this means as far as a database goes. Apparently, it is like having a database backup inside the existing database. I guess there is some advantage to doing that.
Anyway, I can't seem to find anywhere online that will allow me to do this.
I have found a few posts on here about copying the schema without data, but I need the data too.
Backup SQL Schema Only?
How do I check to see if a schema exists, delete it if it does, and then create a schema that accepts data in the current database?
Once I have the new schema created, can I dump data in there with a simple command like this?
SELECT * INTO [dbobackup].Table1 FROM [dbo].Table1;
That line only backs up one table, though. If I need to do this to 245 tables for this particular customer, I'd need a script.
We have several customers, too, and their databases are not structured identically.
Could I do something along these lines?
I was thinking about creating a small console program to walk through the tables.
How would I modify something like the code below to do what I want?
public static void Backup(string sqlConnection)
{
using (var conn = new SqlConnection(sqlConnection))
{
conn.Open();
var tables = new List<String>();
var sqlSelectTables = "SELECT TableName FROM [dbo];";
using (var cmd = new SqlCommand(sqlSelectTables, conn))
{
using (var r = cmd.ExecuteReader())
{
while (r.Read())
{
var item = String.Format("{0}", r["TableName"]).Trim();
tables.Add(item);
}
}
}
var fmtSelectInto = "SELECT * INTO [dbobackup].{0} FROM [dbo].{0}; ";
using (var cmd = new SqlCommand(null, conn))
{
foreach (var item in tables)
{
cmd.CommandText = String.Format(fmtSelectInto, item);
cmd.ExecuteNonQuery();
}
}
}
}
SQL Server already has this built in. If you open SQL Server Management Studio and right click on the database you want to back up, then select all tasks then backup, you will get an option to back up your database into an existing database.
This is the important part and why you should use the built in functionality: You must copy the data from one DB to the other DB in the correct order or you'll get foreign key errors all over the place. If you have a lot of data tables with a lot of relationships, this will really be hard to nail down on your own. You could write code to make a complete graph of all of the dependencies and then figure out what order to copy the table data (which is essentially what SQL Server already does).
Additionally, there are third-party programs available to do this type of backup as well (see: Google).
This is sort of a "work in progress" approach I got started with that looks promising:
public static void CopyTable(
string databaseName, // i.e. Northwind
string tableName, // i.e. Employees
string schema1, // i.e. dbo
string schema2, // i.e. dboarchive
SqlConnection sqlConn)
{
var conn = new Microsoft.SqlServer.Management.Common.ServerConnection(sqlConn);
var server = new Microsoft.SqlServer.Management.Smo.Server(conn);
var db = new Microsoft.SqlServer.Management.Smo.Database(server, databaseName);
db.Tables.Refresh();
for (var itemId = 0; itemId < db.Tables.Count; itemId++)
{
var table = db.Tables.ItemById(itemId);
if (table.Name == tableName)
{
table.Schema = String.Format("{0}", DatabaseSchema.dboarchive);
table.Create();
}
}
}
The only issue I am currently running into is that my db variable always comes back with Tables.Count == 0.
If I get a chance to fix this, I will update.
For now, I've been told to remove this piece of code and check my code in.

How can you connect to a ProgressDB data provider with Dapper?

Please read the comments of the answer for a more complete understanding of what the problem is/was
First, I read through a lot of the other SO questions related to this and still can't get this to work with a basic setup. Here is the related question I have already read:
Passing query parameters in Dapper using OleDb
EDIT: The troubleshooting below is somewhat misleading. The only thing that was going wrong was the query syntax from the Github example was not valid using the ProgressDB OpenEdge driver.
The problem with that question's answer and with the example given in the documented Git examples is that a true ODBC object is not being used, but rather an OleDbConnection object. This causes problems with the scenario where I am trying to use Dapper. Some background and restrictions to my scenario:
I cannot change the DB technology, we are connecting to an Progress DB. The connection string to connect to the DB: connectionString="PROVIDER=MSDASQL;DRIVER={Progress OpenEdge 10.2A Driver};HOST=...;PORT=...;DB=mfgsys;UID=...;PWD=...;DIL=READ UNCOMMITTED" Notice the Provider: MSDASQL
According to MSDN, https://msdn.microsoft.com/en-us/library/a6cd7c08%28v=vs.110%29.aspx - "The .NET Framework Data Provider for OLE DB does not work with the OLE DB provider for ODBC (MSDASQL). To access an ODBC data source using ADO.NET, use the .NET Framework Data Provider for ODBC."
When I attempt to use the OdbcConnection object with Dapper I get the following error: "System.Data.Odbc.OdbcException : ERROR [HY000] [DataDirect][ODBC Progress OpenEdge Wire Protocol driver][OPENEDGE]Syntax error in SQL statement at or about "= ?, Age = ?" (10713)"
I am using the exact same query syntax as the other SO question:
var row = _odbcConn.Query("select Id = ?, Age = ?", new DynamicParameters(new{foo = 12, bar = 23}) {RemoveUnused = false}).Single();
I also removed the DynamicParameters object and attempted with a dynamic object with same result:
var row = _odbcConn.Query("select Id = ?, Age = ?", new{foo = 12, bar = 23}).Single();
Is there a way to accomplish this simple query using an OdbcConnection object? Or does this really have more to do with the specific Progress driver we are using and as such precludes using Dapper?
Edit
Including working ADO.Net code per requests below, the Build.FromReader<EmployeeDataModel>(reader) just loops through the reader and maps the columns with hard coding and is confirmed to work:
public class EmployeeRepository : IEmployeeRepository
{
private readonly OdbcConnection _sqlConn = new OdbcConnection();
public EmployeeRepository() : this(ConfigurationManager.ConnectionStrings["TCI_Epicor"].ConnectionString) { }
public EmployeeRepository(string connString)
{
_sqlConn.ConnectionString = connString;
}
public EmployeeDataModel GetById(string id)
{
try
{
_sqlConn.Open();
using (OdbcCommand command = new OdbcCommand())
{
command.Connection = _sqlConn;
command.CommandType = CommandType.Text;
command.CommandText = GetEmployeeDataQuery();
command.Parameters.Add("empID", OdbcType.NVarChar);
command.Parameters["empID"].Value = id;
var reader = command.ExecuteReader();
return Build.FromReader<EmployeeDataModel>(reader);
}
}
catch
{
return new EmployeeDataModel();
}
finally
{
_sqlConn.Close();
}
}
private string GetEmployeeDataQuery()
{
var sb = new StringBuilder();
sb.AppendLine("SELECT EmpID as 'EmployeeID',");
sb.AppendLine(" FirstName + ' ' + LastName as 'EmployeeName'");
sb.AppendLine(" FROM MFGSYS.PUB.EmpBasic");
sb.AppendLine(" WHERE EmpID = ?");
return sb.ToString();
}
}
If the problem is using anonymous (?) parameters, then:
var row = _odbcConn.Query(
"select Id = ?foo?, Age = ?bar?", new { foo = 12, bar = 23 }
).Single();
Dapper will rewrite that as per your original query, but will know which parameter to put where.
However, if the problem is that the ODBC provider does not support parameters: I can't help much with that :( If you can show how to do it in working ADO.NET code, I can probably show you how to do it easier via dapper.

Open a connection to DB using EF to execute adhoc query

I'm an asp.net guy hard-core and EF + MVC = ME + WTF.
I have a task to open a connection to each of our production database servers. Run a simple query "Select top 1 * from t1 where f1 > 1".
I thought I could just use system.data.sqlclient build the conn string, open the conn and execute a query.
That doesn't seem to be working. Each connection takes forever.
How would I get an instance of our db object to do this with EF. I've seen tons of dbcontext examples but I don't even know how to get that and what it is.
I need to connect to 20 seperate DB1,TBL1,FLD1 and execute the query above. If they all succeed return an int 200 to an MVC view if even one fails just return a 503.
Thanks!
You can get a reference to the underlying DbConnection in your EF using Database.Connection.
For example:
var dbConn = context.Database.Connection;
var cmd = dbConn.CreateCommand();
cmd.CommandText = "SELECT TOP 1 * from t1 WHERE f1 > 1";
var results = cmd.ExecuteReader();
More on Raw SQL Queries with Entity Framework
From Microsoft doc - Sending Raw Commands To The Database
A- If you do not know the entity
using (var context = new BloggingContext())
{
var blogNames = context.Database.SqlQuery<string>(
"SELECT Name FROM dbo.Blogs").ToList();
}
B- If you know the entity
using (var context = new BloggingContext())
{
var blogs = context.Blogs.SqlQuery("SELECT * FROM dbo.Blogs").ToList();
}

Very basic database concepts in C#

I am writing a console program in C# and I need to use a database.
I am looking for very basic tutorials on connecting with and using a db from a C# console program. I haven't been able to find anything basic enough yet and I hope people here can help me find the info I need. I've read the material on MSDN, but MSDN assumes basic knowledge about these things that I am still looking for.
I have created a db within VS Express in my project, created tables, and written some starter records into the tables. I'm trying to find out exactly what each of these things is, and how to determine how to apply them in my project:
SQLConnection
SQLConnection class
SQLCommand
SQLDataAdapter
DataSets
Thanks.
Something like:
using System.Data;
using System.Data.SqlClient;
using(SqlConnection connection = new SqlConnection("")){
SqlCommand command = new SqlCommand(#"
insert into
tblFoo (
col1,
col2
) values (
#val1,
#val2
)",
connection
);
SqlParameter param = new SqlParameter("#val1", SqlDbType.NVarChar);
param.Value = "hello";
command.Parameters.Add(param);
param = new SqlParameter("#val2", SqlDbType.NVarChar);
param.Value = "there";
command.Parameters.Add(param);
command.ExecuteNonQuery();
connection.Close();
}
-- Edit:
Though, of course, when you start doing serious things, I recommend an ORM. I use LLBLGen (it costs money, but most definitely worth it).
-- Edit:
SqlConnection
The thing through which you communicate to the database. This will hold the name of the
server, the username, password, and other misc things.
SqlCommand
Something that holds the sql statement you want to send to the server. This may be an 'update' or 'insert' or 'select' or anything. Depending on what it is, you use a different method to execute it, to possible get data back.
SqlDataAdapter
A strange one; it's used specifically to fill a 'DataSet'. It basically does a bit of work for you, adding the information it finds to the set.
DataSet
Not sure how simple you want this. It's just a collection of returned data, in a table-like format, that you can iterate over. It contains DataTables, because some queries can return more than one table. Typically, though, you'll only have one table, and you can bind to it, or whatever.
Create a sqlconnection, Open it, Create a sqlcommand, execute it to get a sqldatareader, voila. You won't need a dataadapter for a simple example.
string connectionString = "...";
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
string sql = "select field from mytable";
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Console.WriteLine(rdr[0]);
}
}
There's a tutorial on ADO.NET that covers a lot of the things you're looking for at http://www.csharp-station.com/Tutorials/AdoDotNet/Lesson01.aspx. Lesson 1 is mostly background but lesson 2 and onwards goes over SQL client objects.
Another tutorial at http://www.codeproject.com/KB/database/sql_in_csharp.aspx covers some of the basics (SqlConnection, SqlCommand).
I bought a book called Pragmatic ADO.NET.
Well, there are two ways to interact with a SQL Server database in C#. The first is with LINQ, and the second is with the SqlClient library.
LINQ
Ever since .NET 3.0, we've had access to LINQ, which is a pretty impressive ORM and way to deal with collections and lists. There are two different ways that LINQ can work with a database. They are:
LINQ to SQL
LINQ to Entities
Scott Gu has a pretty good tutorial on LINQ to SQL, as well. I'd recommend LINQ to SQL for just getting started, and you can use a lot of that in LINQ to Entities going forward.
A sample select to grab all customers in New York would be:
var Custs = from c in Customers
where c.State = 'NY'
select c;
foreach(var Cust in Custs)
{
Console.WriteLine(Cust.Name);
}
SqlClient
The traditional C# way to hit a SQL Server database (pre-.NET 3.0) has been via the SqlClient library. Essentially, you create a SqlConnection to open up a connection to the database. If you need help with your connection strings, check out ConnectionStrings.com.
After you've connected to your database, you will use the SqlCommand object to interact with it. The most important property for this object is the CommandText. This accepts SQL as its language, and will run raw SQL statements against the database.
If you're doing an insert/update/delete, you will use the ExecuteNonQuery method of SqlCommand. However, if you're doing a select, you will use ExecuteReader and return a SqlDataReader. You can then iterate through the SqlDataReader to get your results.
The following is the code to grab all customers in New York, again:
using System.Data;
using System.Data.SqlClient;
//...
SqlConnection dbConn = new
SqlConnection("Data Source=localhost;Initial Catalog=MyDB;Integrated Security=SSPI");
SqlCommand dbComm = new SqlCommand();
SqlDataReader dbRead;
dbConn.Open();
dbComm.Connection = dbConn;
dbComm.CommandText = "select name from customers where state = #state";
dbComm.Parameters.Add("#state", System.Data.SqlDbType.VarChar);
dbComm.Parameters["#state"].Value = "NY";
dbRead = dbComm.ExecuteReader();
if(dbRead.HasRows)
{
while(dbRead.Read())
{
Console.WriteLine(dbRead[0].ToString());
}
}
dbRead.Close();
dbConn.Close();
Hopefully this gives you a good intro to what each approach does and how to learn more.
In general, I recommend using the Microsoft Enterprise Library for DB access. I've used it in a few projects, and am very fond of it.
See the Data Access Quickstart provided by Microsoft that should help you get started
Also, I've also grown accustomed to writing Extension Methods for extracting data from DataRows. For example, I can do something like this:
//Create an extension method, Value,
//to extract a certain type from a DataRow,
//supplying a default value to be used if DbNull.Value is encountered
DateTime someDateValue = dr["SomeDatabaseField"].Value(new DateTime());
Hope this helps!
See ADO.NET Sample Application
Examples cover
SqlClient
using System;
using System.Data;
using System.Data.SqlClient;
class Sample
{
public static void Main()
{
SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");
SqlCommand catCMD = nwindConn.CreateCommand();
catCMD.CommandText = "SELECT CategoryID, CategoryName FROM Categories";
nwindConn.Open();
SqlDataReader myReader = catCMD.ExecuteReader();
while (myReader.Read())
{
Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1));
}
myReader.Close();
nwindConn.Close();
}
}
OleDb
using System;
using System.Data;
using System.Data.OleDb;
class Sample
{
public static void Main()
{
OleDbConnection nwindConn = new OleDbConnection("Provider=SQLOLEDB;Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");
OleDbCommand catCMD = nwindConn.CreateCommand();
catCMD.CommandText = "SELECT CategoryID, CategoryName FROM Categories";
nwindConn.Open();
OleDbDataReader myReader = catCMD.ExecuteReader();
while (myReader.Read())
{
Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1));
}
myReader.Close();
nwindConn.Close();
}
}
Odbc
using System;
using System.Data;
using System.Data.Odbc;
class Sample
{
public static void Main()
{
OdbcConnection nwindConn = new OdbcConnection("Driver={SQL Server};Server=localhost;" +
"Trusted_Connection=yes;Database=northwind");
OdbcCommand catCMD = new OdbcCommand("SELECT CategoryID, CategoryName FROM Categories", nwindConn);
nwindConn.Open();
OdbcDataReader myReader = catCMD.ExecuteReader();
while (myReader.Read())
{
Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1));
}
myReader.Close();
nwindConn.Close();
}
}

Categories