Coder Social home page Coder Social logo

sqlquery's Introduction

SqlQuery

Fast, lightweight and strongly typed library to query stored procedures. It offers easy and simple to use strongly typed API, supports TVPs as well as multiple result sets.

Setup in 30 seconds

  1. Install-Package SqlQuery
  2. Open SqlQuery.tt and setup connection string, ie.
	sqlQuery.ConnectionString = "Server=.;Database=MyDatabaseName;Trusted_Connection=True;";
  1. Add your Stored Procedure name and save file, to collect result sets T4 will execute stored proc in transaction and roll it back
	.Add(new SqlProc("dbo.GetAllMakesAndModels").ResultSets("Make", "Model"))
  1. Setup is now done, you can now query stored proc:
	var result = Sql.DbRepository.DboGetAllMakesAndModels();
	result.Makes[0].MakeName; // contains your first result set
	result.Models[0].ModelName // contains your second result set

Run & voilla, you just queried database.

Configuration options

Code below declares dbo.GetAllMakesAndModels stored proc and names result sets "Make" and "Model" respectively. Naming result sets is optional, T4 will create collections named Set1, Set2, Set3 and so on.

sqlQuery.Add(new SqlProc("dbo.GetAllMakesAndModels").ResultSets("Make", "Model"));

All parameters are discovered automatically with classes generated for TVP (with strongly typed constructor - in case database definition changes your code will not compile and highlight all touch points to fix), for example to add models declare this in SqlProcs.tt:

sqlQuery.Add(new SqlProc("dbo.AddModels"));

Then in your CS file use:

var models = new List<AddModelsTvp>
{
	new AddModelsTvp("RS5", 4000, true), // strongly typed constructor
	new AddModelsTvp("Q7", 3000, true)
};
Sql.DbRepository.DboAddModels(1, models); // strongly typed proc parameters

And we added 2 new Audi models.

Passing parameters while querying for result set

Some procs may require specific parameter(s) to work and return result sets, you can specify them using SetParameterValue, they are output "as specified":

sqlQuery.Add(new SqlProc("dbo.AddModels").SetParameterValue("makeId", "1"));

All returned properties are non nullable

By default all properties on result classes are non nullable to make it easier to consume data. Any nullable column will be replaced with default(myType). If you want to return nullable items declare them explicitly by adding semicolon after result set and listing column names:

sqlQuery.Add(new SqlProc("dbo.GetAllMakesAndModels").ResultSets("Make", "Model;EngineCapacityCc;IsManufactured"));

Now EngineCapacityCc and IsManufactured in "Model" result set are nullable int? and bool? respectively:

var result = await Sql.DbRepository.DboGetAllMakesAndModelsAsync();
var hasEngineCc = result.Models.First().EngineCapacityCc.HasValue ? "Has engine capacity" : "doesn't";

You can also execute arbitrary SQL instead of stored procedure, only requirement is to pass "name" for calling purposes, for example:

sqlQuery.Add(new SqlRawQuery("GetAllTablesInDatabase", "SELECT TOP 10 * FROM sys.tables").ResultSets("Table"));

Then call in the same was as sproc, using passed "name":

var allTables = (await DAO.Sql.DbRepository.GetAllTablesInDatabaseAsync()).Tables;

Changing connection string and Dependency Injection

To change connection string use static method below or integrate into Dependency Injection:

Sql.ConnectionString = "Server=MyAddress;Database=MyDatabaseName;Trusted_Connection=True;";

Recommended approach for bigger applications is to integrate with your IoC container, sample for NInject:

public class MyModule : NinjectModule
{
	public override void Load()
	{
		Bind<ISqlExecuteConnectionManager>().To<SqlConnectionManager>();
		Bind<ISqlExecute>().To<SqlExecute>();
		Bind<IDbRepository>().To<DbRepository>();
	}
}

You need to implement SqlConnectionManager, easiest option is to inherit from generated SqlExecuteConnectionManager class:

public class SqlConnectionManager : SqlExecuteConnectionManager
{
	public override string GetConnectionString()
	{
		return "Server=MyAddress;Database=MyDatabaseName;Trusted_Connection=True;";
	}
}

If you want more control then you can implement interface instead:

public class SqlConnectionManager : ISqlExecuteConnectionManager
{
	public string GetConnectionString() => System.Configuration.ConfigurationManager.ConnectionStrings["MainDatabase"].ConnectionString;

	public SqlConnection GetSqlConnection() => new SqlConnection(GetConnectionString());
}

Async queries

In real life you'll likely need Async queries, DbRepository has Async versions for each proc returning Task (remember to check IsFaulted and inspect Exception in continuations):

static async Task QueryAsync()
{
	var result = await Sql.DbRepository.DboGetAllMakesAndModelsAsync();

	result.Makes.ForEach(make =>
		Console.WriteLine(string.Join("\n",
				result.Models
				.Where(model => model.MakeId == make.MakeId)
				.Select(model => $"{make.MakeName} {model.ModelName}"))));
}

Extending generated objects

Sometimes you need extra property or method to aggregate or interpret results. This can be done thanks to partial classes:

public partial class DboGetAllMakesAndModelsResult
{
	public partial class Model
	{
		public bool IsEngineOver2000cc => this.EngineCapacityCc > 2000;
	}
}

Documentation ToDo

  • Generating dictionaries from database as Enum in code
  • Handling timeouts and deadlocks

Dealing with problems

Should you encounter a problem try to open SqlQuery.tt and select "Current Document" in "Error list". This will show only issues related to SqlQuery instead of flooding window with large numbers of errors caused by side effects.

Remember TT will only regenerate if you save SqlProcs.tt or "Run Custom Tool" in Visual Studio. Any suggestions are welcome.

sqlquery's People

Contributors

sebbie avatar

Stargazers

 avatar

sqlquery's Issues

Support for uniqueidentifiers

Currently uniqueidentifier fails with "Error converting data type varchar to uniqueidentifier" message:

Severity	Code	Description	Project	File	Line	Suppression State
Error		Running transformation: System.Exception: SqlCommand='EXEC dbo.GuidTest @guidParam=''' ConnectionString='(redacted)' ---> System.Data.SqlClient.SqlException: Error converting data type varchar to uniqueidentifier.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader()
   at Microsoft.VisualStudio.TextTemplating40D6E0CCC43485BFF51860F2AA60163346760CFBE3B9C549B8A84E9E55F88684882C151DF4BEEB8D6D6C6C3950958DD12C826F3EC86C79F76C8A9D435644F368.GeneratedTextTransformation.SqlQuery.InspectResultSets(String sqlCommand, Action`2 readRow)
   --- End of inner exception stack trace ---
   at Microsoft.VisualStudio.TextTemplating40D6E0CCC43485BFF51860F2AA60163346760CFBE3B9C549B8A84E9E55F88684882C151DF4BEEB8D6D6C6C3950958DD12C826F3EC86C79F76C8A9D435644F368.GeneratedTextTransformation.SqlQuery.InspectResultSets(String sqlCommand, Action`2 readRow)
   at Microsoft.VisualStudio.TextTemplating40D6E0CCC43485BFF51860F2AA60163346760CFBE3B9C549B8A84E9E55F88684882C151DF4BEEB8D6D6C6C3950958DD12C826F3EC86C79F76C8A9D435644F368.GeneratedTextTransformation.SqlQuery.ReadDatabase()
   at Microsoft.VisualStudio.TextTemplating40D6E0CCC43485BFF51860F2AA60163346760CFBE3B9C549B8A84E9E55F88684882C151DF4BEEB8D6D6C6C3950958DD12C826F3EC86C79F76C8A9D435644F368.GeneratedTextTransformation.TransformText()	DAO	...\DAO\SqlQuery.tt	1	
`

Add mySQL support

  • tt based
  • IN/OUT/INOUT parameters
  • "include all routine" mode
  • support for temporary table as a way to pass sets to stored procedure to overcome language limitations
    Out of scope:
  • dotnet command support (TBC)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.