DevFM #20 : SqlDatabaseCommand, un Simple Object Mapping Toolkit
-
Upload
denis-voituron -
Category
Software
-
view
1.396 -
download
0
Transcript of DevFM #20 : SqlDatabaseCommand, un Simple Object Mapping Toolkit
1
Denis Voituron.Net Software Architect
Simple Object Mapping SqlDatabaseCommand
[email protected] www.dvoituron.be @denisvoituron
2
About meDenis Voituron
Civil engineer (Mons)Company founderDeveloper: VB3, VB.Net, C#.Net Software Architect (NRB)BloggerSpeaker (DevApps.be)
www.dvoituron.be
3
Agenda• Background
• SQL Architecture• ADO.NET• EntityFramework• Comparaison
• Simple Object Mapping• Dapper.NET• SqlDatabaseCommand• SQLite
• SQL Server CLR Stored Procedures
4
Background
5
Architecture
SQL
SQLSQL
6
SCOTT DatabaseEMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO7839 KING PRESIDENT 17-NOV-81 5000 10
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7756 CLARK MANAGER 7839 09-JUN-81 1500 10
... ...
... ...
7456 JONES MANAGER 7839 02-APR-81 2975 20
DEPTNO DNAME LOC10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIOS BOSTON
7
ADO.NETusing (var connection = new SqlConnection(CONNECTION_STRING)){ connection.Open();
connection.Close();}
SELECT ENAME FROM EMP WHERE EMPNO = 7369
using (var cmd = connection.CreateCommand()) { cmd.CommandText = "SELECT ENAME " + " FROM EMP " + " WHERE EMPNO = 7369 ";
}
using (var adapter = new SqlDataAdapter(cmd)) { DataTable table = new DataTable(); adapter.Fill(table); string name = table.Rows[0].Field<string>("ENAME"); }
8
Entity Framework
var db = new SCOTTEntities();
var query = from e in db.EMPs where e.EMPNO == 7369 select e.ENAME;
var name = query.First();
var db = new SCOTTEntities();
var query = from e in db.EMPs where e.EMPNO == 7369 select e;
var name = query.First().DEPT.DNAME; SELECT TOP (1) [Extent1].[ENAME] AS [ENAME] FROM [dbo].[EMP] AS [Extent1] WHERE 7369 = [Extent1].[EMPNO]
SELECT TOP (1) [Extent1].[EMPNO] AS [EMPNO], [Extent1].[ENAME] AS [ENAME], [Extent1].[JOB] AS [JOB], [Extent1].[MGR] AS [MGR], [Extent1].[HIREDATE] AS [HIREDATE], [Extent1].[SAL] AS [SAL], [Extent1].[COMM] AS [COMM], [Extent1].[DEPTNO] AS [DEPTNO] FROM [dbo].[EMP] AS [Extent1] WHERE 7369 = [Extent1].[EMPNO]
SELECT [Extent1].[DEPTNO] AS [DEPTNO], [Extent1].[DNAME] AS [DNAME], [Extent1].[LOC] AS [LOC] FROM [dbo].[DEPT] AS [Extent1] WHERE [Extent1].[DEPTNO] = @V1
Object Relational Mapping
9
ADO.NET vs Entity Framework
http://stackoverflow.com/questions/2698151/entity-framework-vs-linq-to-sql-vs-ado-net-with-stored-procedures
Performance
Speed of Development
Maintainable code (neat)
Flexibility
Scalability
ADO EF
10
Performances
http://blogs.msdn.com/b/adonet/archive/2012/02/14/sneak-preview-entity-framework-5-0-performance-improvements.aspx
11
Simple Object Mapping
12
• Library that will extend IDbConnection
• Need an opened connection
Dapper.NET
https://github.com/StackExchange/dapper-dot-net
using (var connection = new SqlConnection(CONNECTION_STRING)){ connection.Open();
string sql = "SELECT * FROM EMP WHERE EMPNO = @Id"; var emp = connection.Query<EMP>(sql, new { Id = 7369 }); }
13
• Query
• Query Dynamic
• ExecuteScalar
• Execute
• Buffered
Dapper.NETstring sql = "SELECT * FROM EMP WHERE EMPNO = @Id";var emp = connection.Query<EMP>(sql, new { Id = 7369 });
string sql = "SELECT * FROM EMP WHERE EMPNO = @Id";var emp = connection.Query(sql, new { Id = 7369 });
string sql = "SELECT ENAME FROM EMP WHERE EMPNO = @Id";var emp = connection.ExecuteScalar<string>(sql, new { Id = 7369 });
var n = connection.Execute(“DELETE FROM EMP");
var emp = connection.Query(sql, buffered: false);
14
SqlDatabaseCommand• Object and Commands
• Construction and neat destruction• Optimizing SQL and Parameters (avoid SQL
injection)• Automatic conversion to C# objects• Generation of C# entities• Management of logs and traces
• Extension method of System.Data• Transform C# properties to SQL parameters• DBNull• ...https://github.com/Apps72/Dev.Data
15
SqlDatabaseCommand• Sample
https://github.com/Apps72/Dev.Data
using (var cmd = new SqlDatabaseCommand(CONNECTION_STRING)){
}
cmd.CommandText.AppendLine(" SELECT * "); cmd.CommandText.AppendLine(" FROM EMP ");
var emps = cmd.ExecuteTable<Employee>();
cmd.CommandText.AppendLine(" WHERE HIREDATE = @HireDate "); cmd.Parameters.AddValues(new { HireDate = new DateTime(1980, 12, 17) });
16
9876 NEW
• Main methodsSqlDatabaseCommandEMPNO ENAME
7839 KING
7698 BLAKE
7756 CLARK
...
...
7456 JONES
var emps = cmd.ExecuteTable<Employee>();
• ExecuteTable
var smith = cmd.ExecuteRow<Employee>();
• ExecuteRow
var name = cmd.ExecuteScalar<String>();
• ExecuteScalar
var n = cmd.ExecuteNonQuery();
• ExecuteQuery
17
• ParametersSqlDatabaseCommand
cmd.CommandText.AppendLine(" SELECT ENAME ") .AppendLine(" FROM EMP ") .AppendLine(" WHERE EMPNO = @EmpNo ") .AppendLine(" AND HIREDATE = @HireDate ");
cmd.Parameters.AddWithValue("@EmpNo", 7369);cmd.Parameters.AddWithValue("@HireDate", new DateTime(1980, 12, 17));
var name = cmd.ExecuteScalar();
cmd.CommandText.AppendLine(" SELECT ENAME ") .AppendLine(" FROM EMP ") .AppendLine(" WHERE EMPNO = @EmpNo ") .AppendLine(" AND HIREDATE = @HireDate ");
cmd.Parameters.AddValues(new { EmpNo = 7369, HireDate = new DateTime(1980, 12, 17) });
var name = cmd.ExecuteScalar();
18
• Traces• Logging
• Query Formatter
SqlDatabaseCommandcmd.Log = Console.WriteLine;
cmd.Log = (message) => { Console.WriteLine(message); };
string formatted = cmd.GetCommandTextFormatted(QueryFormat.Text);
SELECT ENAME FROM EMP WHERE EMPNO = 7369 AND HIREDATE = '1970-05-04 14:15:16'
string formatted = cmd.GetCommandTextFormatted(QueryFormat.Html);
SELECT ENAME FROM EMP WHERE EMPNO = 7369 AND HIREDATE = '1970-05-04 14:15:16'
19
• Entities GeneratorSqlDatabaseCommand
T4
Entities.tt
// *********************************************// Code Generated with Apps72.Dev.Data.Generator// *********************************************using System;
namespace Data.Tests.Entities{ /// <summary /> public partial class BONUS { /// <summary /> public virtual String ENAME { get; set; } /// <summary /> public virtual String JOB { get; set; } /// <summary /> public virtual Int32? SAL { get; set; } /// <summary /> public virtual Int32? COMM { get; set; } } /// <summary /> public partial class DEPT { /// <summary /> public virtual Int32 DEPTNO { get; set; } /// <summary /> public virtual String DNAME { get; set; } /// <summary /> public virtual String LOC { get; set; } }
Save
var entitiesGenerator = new SqlEntitiesGenerator(CONNECTION_STRING);foreach (var table in entitiesGenerator.Tables){ ...}
20
• Best PracticeSqlDatabaseCommandpublic class DataService : IDataService{ public SqlDatabaseCommand GetDatabaseCommand() { return new SqlDatabaseCommand(CONNECTION_STRING); }
public SqlDatabaseCommand GetDatabaseCommand(SqlTransaction trans) { return new SqlDatabaseCommand(trans.Connection, trans); }} using (var cmd =
service.GetDatabaseCommand()){ ...}
21
• Microsoft.Data.Sqlite• SqliteDatabaseCommand
SQLitehttps://www.myget.org/F/aspnetcidev/api/v2
public SqliteDatabaseCommand GetDatabaseCommand(){ return new SqliteDatabaseCommand("Filename=Scott.db");}
public IEnumerable<Scott.EMP> GetAllEmployees(){ using (var cmd = this.GetDatabaseCommand()) { cmd.CommandText.AppendLine(" SELECT * FROM EMP "); return cmd.ExecuteTable<Scott.EMP>(); }}
22
CLR Stored Procedures
23
• What?• You can now write stored procedures, triggers, user-
defined types, user-defined functions, user-defined aggregates, and streaming table-valued functions, using any .NET Framework language
• Why?• Performances• Development tools (VS, GIT, …)• Centralisation du code• Déploiement
CLR Stored Procedures
https://msdn.microsoft.com/en-us/library/ms131102.aspx
24
• Create a Class Library• CLR Nuget Package
SqlDatabaseCommand
25
SqlDatabaseCommand[SqlFunction(DataAccess = DataAccessKind.Read)]public static int GetMaximumAge(){ using (var cmd = new SqlDatabaseCommand("context connection=true")) { ... }}
C#
CREATE FUNCTION GetMaximumAge()RETURNS INT AS EXTERNAL NAME SampleSqlDatabaseCommandClr.SampleCLR.GetMaximumAge
SQL
26
SqlDatabaseCommand[SqlFunction()]public static bool IsComparableTo(string text1, string text2){ return text1.ComparableTo(text2) == 0;}
SELECT dbo.IsComparableTo('Maison', 'House') -- FALSESELECT dbo.IsComparableTo('St Ecole', 'Saint''école&') -- TRUESELECT dbo.IsComparableTo('A''&é', 'aE') -- TRUE
27
Simple Object Mapping
ADO.NET EntityFramework
SQLite
Dapper.NETSqlDatabaseCommandCLR Stored Procedure
SQL Databases
Conclusion
Samples: https://github.com/dvoituron/SampleSqlDatabaseCommand