aceryansoft.sqlflow
1.24.5.15
dotnet add package aceryansoft.sqlflow --version 1.24.5.15
NuGet\Install-Package aceryansoft.sqlflow -Version 1.24.5.15
<PackageReference Include="aceryansoft.sqlflow" Version="1.24.5.15" />
paket add aceryansoft.sqlflow --version 1.24.5.15
#r "nuget: aceryansoft.sqlflow, 1.24.5.15"
// Install aceryansoft.sqlflow as a Cake Addin
#addin nuget:?package=aceryansoft.sqlflow&version=1.24.5.15
// Install aceryansoft.sqlflow as a Cake Tool
#tool nuget:?package=aceryansoft.sqlflow&version=1.24.5.15
aceryansoft.sqlflow
C# light and fluent wrapper to easily use multiple sql databases (Sql server,Oracle,PostgreSql,Mysql,Sybase) with the same code while targeting dotnet standard 2.0 / 2.1 , dotnet framework 4.6.1 and above.
aceryansoft.sqlflow is not a real ORM (Object-Relational-Mapping), it is just a small contribution to help others who are old enough to build and query their own sql schemas.
Install
Using nuget
PM> Install-Package aceryansoft.sqlflow
Using .net cli
dotnet add package aceryansoft.sqlflow
Release note
Please read Release note .
Features
Please read Documentation .
ExecuteReaderAndMap
Hello sql world
using System;
using System.Collections.Generic;
using aceryansoft.sqlflow;
namespace aceryansoft.sqlflow.console
{
class Program
{
static void Main(string[] args)
{
var sqlServerExecuter = SqlFlow.Create("connection String").WithSqlServerExecuter();
// select other SGBD .WithMySqlExecuter() .WithOracleExecuter() .WithPostGreSqlExecuter() .WithSybaseExecuter()
var peopleQuery = @"select pe.idperson
,pe.name, pe.age
, pe.dateofbirth 'BirthDay'
, co.phone , co.city, co.postalcode
from Persons pe
inner join Contacts co on pe.idperson= co.idperson
where pe.dateofbirth <= @dateofbirth ";
var peoples = sqlServerExecuter.ExecuteReaderAndMap<Person>(peopleQuery,
propertiesMapping: new Dictionary<string, string>()
{ // -- Auto mapping of fields name, age,BirthDay to Properties of object Person
{"idperson", "id" }, // map idperson value to id property of object Person
{"phone", "Contacts.PhoneNumber" },
{"city", "Contacts.Home.City" }, // map city value to property Person.Contacts.Home.City
{"postalcode", "Contacts.Home.PostalCode" }
},
queryParameters: new Dictionary<string, object>()
{
{"@dateofbirth", new DateTime( 1980,01,20) } // pass @dateofbirth to the sql query
});
Console.WriteLine($"Hello sql world ! we found {peoples.Count} people(s)");
}
}
public class Person
{
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public DateTime BirthDay { get; set; }
public Contact Contacts { get; set; }
}
public class Contact
{
public String PhoneNumber { get; set; }
public Address Home { get; set; }
}
public class Address
{
public string City { get; set; }
public int PostalCode { get; set; }
}
}
ExecuteScalar
var oracleExecuter = SqlFlow.Create("connection String").WithOracleExecuter();
var someValue = oracleExecuter.ExecuteScalar<int>("select top 1 age from Persons");
ExecuteNonQuery
var sybaseExecuter = SqlFlow.Create("connection String").WithSybaseExecuter();
sybaseExecuter.ExecuteNonQuery("update Persons set age = age+1 where dateofbirth <= @dateofbirth",
queryParameters: new Dictionary<string, object>()
{
{"@dateofbirth", new DateTime( 1980,01,20) } // pass @dateofbirth to the sql query
});
ExecuteReader
using aceryansoft.sqlflow.Helpers;
var peoples = new List<Person>();
var postgreExecuter = SqlFlow.Create("connection String").WithPostGreSqlExecuter();
postgreExecuter.ExecuteReader(
@"select pe.idperson
,pe.name, pe.age
, pe.dateofbirth 'BirthDay'
, co.phone , co.city, co.postalcode
from Persons pe
inner join Contacts co on pe.idperson= co.idperson
where pe.dateofbirth <= @dateofbirth ",
reader=>
{
peoples.Add(new Person()
{
Id = reader.GetValue<long>("idperson"),
Age = reader.GetValue<int>("age"),
Name = reader.GetValue<string>("name"),
BirthDay = reader.GetValue<DateTime>("BirthDay", DateTime.Now.AddDays(-10)),
Contacts = new Contact()
{
PhoneNumber = reader.GetValue<string>("phone"),
Home = new Address()
{
City = reader.GetValue<string>("city"),
PostalCode = reader.GetValue<int>("postalcode"),
}
}
});
},
queryParameters: new Dictionary<string, object>()
{
{"@dateofbirth", new DateTime( 1980,01,20) } // pass @dateofbirth to the sql query
});
Console.WriteLine($"Read sql records with custom logic, we found {peoples.Count} people(s)");
store procedure
var peoples = new List<Person>();
var mySqlExecuter = SqlFlow.Create("connection String").WithMySqlExecuter();
var spParameters = new Dictionary<string, object>()
{
{"@age", 21 },
{"@name", "yannick" },
{"@birthday", DateTime.Now.AddYears(-21) }
};
var newpersonId = mySqlExecuter.ExecuteScalar<decimal>(
query: @"sp_insert_persons"
, queryParameters: spParameters
,isStoreProcedure:true); // set isStoreProcedure=true to execute query as store procedure
Console.WriteLine($"execute store procedure and get new person id = {newpersonId}");
//store procedure can also be called with ExecuteReader, ExecuteNonQuery, ExecuteReaderAndMap
Transaction
var oracleExecuter = SqlFlow.Create("connection String").WithOracleExecuter();
oracleExecuter.RunTransaction((sqlexecuter, dbConnexion, dbTransaction) =>
{
var storeprocParams = new Dictionary<string, object>()
{
{"@age", 21 },
{"@name", "yannick" },
{"@birthday", DateTime.Now.AddYears(-21) }
};
var newpersonId = sqlexecuter.ExecuteScalar<decimal>(
query: @"sp_insert_persons"
, queryParameters: storeprocParams
, isStoreProcedure: true);
var spcontactParams = new Dictionary<string, object>()
{
{"@idperson", newpersonId },
{"@phone", "007" },
{"@city", "paris" },
{"@postalcode", 78300 }
};
sqlexecuter.ExecuteNonQuery(
query: @"sp_insert_contact"
, queryParameters: spcontactParams
, isStoreProcedure: true);
});
Bulk insert
Classic sql bulkinsert, available on Oracle, Mysql and Sql server
var oracleExecuter = SqlFlow.Create("connection String").WithOracleExecuter(); // .WithSqlServerExecuter() .WithMySqlExecuter()
var peoples = new List<Person>()
{
new Person(){Name="yan", Age=21},
new Person(){Name="pierre", Age=51},
new Person(){Name="philippe", Age=43},
new Person(){Name="marc", Age=27},
new Person(){Name="edouard", Age=62, Contacts = new Contact()
{
Home = new Address()
{
City="dakar",
PostalCode=27
},
PhoneNumber = "06"
} },
};
var propertyMapping = new Dictionary<string, string>() {{ "Name","user_name" } , { "Age", "age" } };
oracleExecuter.BulkInsert<Person>("Persons", peoples, propertyMapping, batchSize: 500);
Batch insert
Insert multiple rows by generating insert into query,use the batchSize parameter to ensure that the query size is under the maximum lenght of a sqlcommand. This command is available on PostgreSql, Mysql and Sql server.
var postGreSqlExecuter = SqlFlow.Create("connection String").WithPostGreSqlExecuter(); // .WithSqlServerExecuter() .WithMySqlExecuter()
var peoples = new List<Person>()
{
new Person(){Name="yan", Age=21},
new Person(){Name="pierre", Age=51},
new Person(){Name="philippe", Age=43},
new Person(){Name="marc", Age=27},
new Person(){Name="edouard", Age=62, Contacts = new Contact()
{
Home = new Address()
{
City="dakar",
PostalCode=27
},
PhoneNumber = "06"
} },
};
var propertyMapping = new Dictionary<string, string>() { { "Name", "user_name" }, { "Age", "age" } };
postGreSqlExecuter.BatchInsertRows("Persons", peoples, propertyMapping, batchSize: 500);
Output parameter
var sqlserverExecuter = SqlFlow.Create(_localConnectionString).WithSqlServerExecuter();
int newCustomerId = 0;
sqlserverExecuter.ExecuteNonQuery(
@"Insert into Customers( name , amount , notation , traderid , creationdate )
values(@name, @amount, @notation, @traderid, @creationdate);
select @customerId=@@IDENTITY" // also working with store procedure name and isStoreProcedure:true
, new Dictionary<string, object>() {
{"@name", "corp model x" },
{"@amount", 1503 },
{"@notation", 18.2 },
{"@traderid", 169 },
{"@creationdate", DateTime.Now },
{"@customerId", new QueryParameter<int>()
{
IsOuputParameter = true,
GetOutputParameterValue = (val)=>{newCustomerId = (int) val; }
}
}
});
// newCustomerId now contains the ouput parameter value = last inserted customerId
Multiple query result sets
var sqlserverExecuter = SqlFlow.Create(_localConnectionString).WithSqlServerExecuter();
var Users = new List<SampleUser>();
var Cities = new List<SampleCity>();
var multiResultSetQuery = @"
select 'yannick' as username, 24 as age, 1.8 as height
union
select 'pierre' as username, 34 as age, 1.85 as height
union
select 'anne' as username, 7 as age, 2 as height;
select 'paris' as city, 75001 as postalcode
union
select 'nanterre' as city, 92000 as postalcode";
sqlserverExecuter.ExecuteReaderOnMultipleResultsSet(
multiResultSetQuery,(reader, index)=>
{
if (index == 0)
{
Users.Add(new SampleUser()
{
Name = reader.GetValue<string>("username"),
Age = reader.GetValue<int>("age"),
Height = reader.GetValue<decimal>("height"),
});
}
else if (index == 1)
{
Cities.Add(new SampleCity()
{
Name = reader.GetValue<string>("city"),
PostalCode = reader.GetValue<int>("postalcode")
});
}
});
// Users and Cities collection contains the results of the 2 resultsSet returned by the mixed query
Contributing
All contribution are welcome, please read the Code of conduct and contact the author.
License
This project is licensed under the terms of the Apache-2.0 License. Please read LICENSE file for license rights and limitations.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- AdoNetCore.AseClient (>= 0.19.2)
- MySql.Data (>= 8.4.0)
- Npgsql (>= 8.0.3)
- Oracle.ManagedDataAccess.Core (>= 2.19.230)
- System.Data.SqlClient (>= 4.8.6)
-
.NETStandard 2.1
- AdoNetCore.AseClient (>= 0.19.2)
- MySql.Data (>= 8.4.0)
- Npgsql (>= 8.0.3)
- Oracle.ManagedDataAccess.Core (>= 3.21.140)
- System.Data.SqlClient (>= 4.8.6)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Initial package release