Befindet sich unter https://github.com/dapperlib/dapper/releases
Myget Pre-Release-Feed: https://www.myget.org/gallery/dapper
Paket | Nuget stabil | Nuget Pre-Release | Downloads | Myget |
---|---|---|---|---|
Dapper | ||||
Dapper.EntityFramework | ||||
Dapper.EntityFramework.StrongName | ||||
Dapper.rainbow | ||||
Dapper.SQLBuilder | ||||
Dapper.Strongname |
Paketzwecke:
Dapper wurde ursprünglich für und durch Stapelüberlauf entwickelt, ist aber f/oss. Das Sponsoring ist willkommen und eingeladen - siehe den Sponsor -Link oben auf der Seite. Ein großes Dankeschön an alle (Einzelpersonen oder Organisationen), die Dapper gesponsert haben, aber ein massives Dank insbesondere an:
Dapper ist eine Nuget -Bibliothek, die Sie zu Ihrem Projekt hinzufügen können, das Ihre ADO.NET -Verbindungen über Erweiterungsmethoden für Ihre DbConnection
-Instanz verbessert. Dies liefert eine einfache und effiziente API zum Aufrufen von SQL mit Unterstützung sowohl für den synchronen als auch für den asynchronen Datenzugriff und ermöglicht sowohl gepufferte als auch nicht gepufferte Abfragen.
Es bietet mehrere Helfer, aber die wichtigsten APIs sind:
// insert/update/delete etc
var count = connection . Execute ( sql [ , args ] ) ;
// multi-row query
IEnumerable < T > rows = connection . Query < T > ( sql [ , args ] ) ;
// single-row query ({Single|First}[OrDefault])
T row = connection . QuerySingle < T > ( sql [ , args ] ) ;
Wo args
unter anderem sein können:
Dictionary<string,object>
DynamicParameters
-Instanz public class Dog
{
public int ? Age { get ; set ; }
public Guid Id { get ; set ; }
public string Name { get ; set ; }
public float ? Weight { get ; set ; }
public int IgnoredProperty { get { return 1 ; } }
}
var guid = Guid . NewGuid ( ) ;
var dog = connection . Query < Dog > ( " select Age = @Age, Id = @Id " , new { Age = ( int ? ) null , Id = guid } ) ;
Assert . Equal ( 1 , dog . Count ( ) ) ;
Assert . Null ( dog . First ( ) . Age ) ;
Assert . Equal ( guid , dog . First ( ) . Id ) ;
Diese Methode führt SQL aus und gibt eine dynamische Liste zurück.
Beispiel Verwendung:
var rows = connection . Query ( " select 1 A, 2 B union all select 3, 4 " ) . AsList ( ) ;
Assert . Equal ( 1 , ( int ) rows [ 0 ] . A ) ;
Assert . Equal ( 2 , ( int ) rows [ 0 ] . B ) ;
Assert . Equal ( 3 , ( int ) rows [ 1 ] . A ) ;
Assert . Equal ( 4 , ( int ) rows [ 1 ] . B ) ;
Beispiel Verwendung:
var count = connection . Execute ( @"
set nocount on
create table #t(i int)
set nocount off
insert #t
select @a a union all select @b
set nocount on
drop table #t" , new { a = 1 , b = 2 } ) ;
Assert . Equal ( 2 , count ) ;
Mit derselben Signatur können Sie auch einen Befehl bequem und effizient mehrmals ausführen (z.
Beispiel Verwendung:
var count = connection . Execute ( @"insert MyTable(colA, colB) values (@a, @b)" ,
new [ ] { new { a = 1 , b = 1 } , new { a = 2 , b = 2 } , new { a = 3 , b = 3 } }
) ;
Assert . Equal ( 3 , count ) ; // 3 rows inserted: "1,1", "2,2" and "3,3"
Ein weiterer Beispiel verwendet, wenn Sie bereits eine vorhandene Sammlung haben:
var foos = new List < Foo >
{
{ new Foo { A = 1 , B = 1 } }
{ new Foo { A = 2 , B = 2 } }
{ new Foo { A = 3 , B = 3 } }
} ;
var count = connection . Execute ( @"insert MyTable(colA, colB) values (@a, @b)" , foos ) ;
Assert . Equal ( foos . Count , count ) ;
Dies funktioniert für jeden Parameter, der IEnumerable<T>
für einige t implementiert.
Ein wichtiges Merkmal von Dapper ist die Leistung. Die folgenden Metriken zeigen, wie lange es dauert, um eine SELECT
mit einem DB (in verschiedenen Konfigurationen zu bezeichnen) auszuführen und die an Objekte zurückgegebenen Daten zuzuordnen.
Die Benchmarks finden Sie in Dapper.Tests.Performance (Beiträge willkommen!) Und können über:
dotnet run --project . b enchmarks D apper.Tests.Performance -c Release -f net8.0 -- -f * --join
Ausgabe aus dem neuesten Lauf ist:
BenchmarkDotNet v0.13.7, Windows 10 (10.0.19045.3693/22H2/2022Update)
Intel Core i7-3630QM CPU 2.40GHz (Ivy Bridge), 1 CPU, 8 logical and 4 physical cores
.NET SDK 8.0.100
[Host] : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX
ShortRun : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX
Orm | Verfahren | Zurückkehren | Bedeuten | Stddev | Fehler | Gen0 | Gen1 | Gen2 | Zugewiesen |
---|---|---|---|---|---|---|---|---|---|
Dapper Cache Impact | ExecuteParameters_Cache | Leere | 96.75 US | 0,668 US | 1.010 US | 0,6250 | - - | - - | 2184 b |
Dapper Cache Impact | QueryFirstParameters_cache | Leere | 96.86 US | 0,493 US | 0,746 US | 0,8750 | - - | - - | 2824 b |
Hand codiert | SQLCommand | Post | 119.70 US | 0,706 US | 1.067 US | 1.3750 | 1.0000 | 0,1250 | 7584 b |
Hand codiert | DataTable | dynamisch | 126.64 US | 1.239 US | 1.873 US | 3.0000 | - - | - - | 9576 b |
Sqlmarshal | SQLCommand | Post | 132.36 US | 1.008 US | 1.523 US | 2.0000 | 1.0000 | 0,2500 | 11529 b |
Dapper | QueryFirstordeFault | Post | 133.73 US | 1.301 US | 2.186 US | 1.7500 | 1,5000 | - - | 11608 b |
Mächtig | Abfrage | dynamisch | 133.92 US | 1.075 US | 1.806 US | 2.0000 | 1.7500 | - - | 12710 b |
Linq zu db | Abfrage | Post | 134.24 US | 1.068 US | 1.614 US | 1.7500 | 1.2500 | - - | 10904 b |
Repodb | ExecuteQuery | Post | 135.83 US | 1.839 US | 3.091 US | 1.7500 | 1,5000 | - - | 11649 b |
Dapper | "Abfrage (gepuffert)" | Post | 136.14 US | 1.755 US | 2.653 US | 2.0000 | 1,5000 | - - | 11888 b |
Mächtig | Abfrage | Post | 137.96 US | 1.485 US | 2.244 US | 2.2500 | 1.2500 | - - | 12201 b |
Dapper | QueryFirstordeFault | dynamisch | 139.04 US | 1.507 US | 2.279 US | 3.5000 | - - | - - | 11648 b |
Mächtig | Single aus der Frequerie | dynamisch | 139.74 US | 2.521 US | 3.811 US | 2.0000 | 1.7500 | - - | 12710 b |
Dapper | "Abfrage (gepuffert)" | dynamisch | 140.13 US | 1.382 US | 2.090 US | 2.0000 | 1,5000 | - - | 11968 b |
Servicestack | SinglebyID | Post | 140.76 US | 1.147 US | 2.192 US | 2.5000 | 1.2500 | 0,2500 | 15248 b |
Dapper | "Beitrag bekommen" | Post | 141.09 US | 1.394 US | 2.108 US | 2.0000 | 1,5000 | - - | 12440 b |
Mächtig | Single aus der Frequerie | Post | 141.17 US | 1.941 US | 2.935 US | 1.7500 | 1,5000 | - - | 12201 b |
Massiv | "Abfrage (dynamisch)" | dynamisch | 142.01 US | 4.957 US | 7.494 US | 2.0000 | 1,5000 | - - | 12342 b |
Linq zu db | "Erst (kompiliert)" | Post | 144.59 US | 1.295 US | 1.958 US | 1.7500 | 1,5000 | - - | 12128 b |
Repodb | Queryfield | Post | 148.31 US | 1.742 US | 2.633 US | 2.0000 | 1,5000 | 0,5000 | 13938 b |
Norm | 'Lesen <> (Tupel)' ' | Valuetuple`8 | 148.58 US | 2.172 US | 3.283 US | 2.0000 | 1.7500 | - - | 12745 b |
Norm | 'Read <()> (genannt Tupel)' ' | Valuetuple`8 | 150.60 US | 0,658 US | 1.106 US | 2.2500 | 2.0000 | 1.2500 | 14562 b |
Repodb | Abfrage | Post | 152.34 US | 2.164 US | 3.271 US | 2.2500 | 1,5000 | 0,2500 | 14106 b |
Repodb | Querydynamic | Post | 154.15 US | 4.108 US | 6.210 US | 2.2500 | 1.7500 | 0,5000 | 13930 b |
Repodb | Anfragen wo | Post | 155.90 US | 1.953 US | 3.282 US | 2.5000 | 0,5000 | - - | 14858 b |
Dapper Cache Impact | Executenoparameters_nocache | Leere | 162.35 US | 1.584 US | 2.394 US | - - | - - | - - | 760 b |
Dapper Cache Impact | Executenoparameters_cache | Leere | 162.42 US | 2.740 US | 4.142 US | - - | - - | - - | 760 b |
Dapper Cache Impact | QueryFirstnoparameters_cache | Leere | 164.35 US | 1.206 US | 1.824 US | 0,2500 | - - | - - | 1520 b |
Devexpress.xpo | FindObject | Post | 165.87 US | 1.012 US | 1.934 US | 8.5000 | - - | - - | 28099 b |
Dapper Cache Impact | Queryfirstnoparameters_nocache | Leere | 173.87 US | 1.178 US | 1.781 US | 0,5000 | - - | - - | 1576 b |
Linq zu db | Erste | Post | 175.21 US | 2.292 US | 3.851 US | 2.0000 | 0,5000 | - - | 14041 b |
EF 6 | SQLQuery | Post | 175.36 US | 2.259 US | 3.415 US | 4.0000 | 0,7500 | - - | 24209 b |
Norm | 'Lesen <> (Klasse)' ' | Post | 186.37 US | 1.305 US | 2.496 US | 3.0000 | 0,5000 | - - | 17579 b |
Devexpress.xpo | GetObjectByKey | Post | 186.78 US | 3.407 US | 5.151 US | 4.5000 | 1.0000 | - - | 30114 b |
Dapper | 'Abfrage (nicht leichter)' ' | dynamisch | 194.62 US | 1.335 US | 2.019 US | 1.7500 | 1,5000 | - - | 12048 b |
Dapper | 'Abfrage (nicht leichter)' ' | Post | 195.01 US | 0,888 US | 1.343 US | 2.0000 | 1,5000 | - - | 12008 b |
Devexpress.xpo | Abfrage | Post | 199.46 US | 5.500 US | 9.243 US | 10.0000 | - - | - - | 32083 b |
Belgrad | FirstorDefault | Task`1 | 228.70 US | 2.181 US | 3.665 US | 4.5000 | 0,5000 | - - | 20555 b |
EF -Kern | "Erst (kompiliert)" | Post | 265.45 US | 17.745 US | 26.828 US | 2.0000 | - - | - - | 7521 b |
Nhibernate | Erhalten | Post | 276.02 US | 8.029 US | 12.139 US | 6.5000 | 1.0000 | - - | 29885 b |
Nhibernate | HQL | Post | 277.74 US | 13.032 US | 19.703 US | 8.0000 | 1.0000 | - - | 31886 b |
Nhibernate | Kriterien | Post | 300.22 US | 14.908 US | 28.504 US | 13.0000 | 1.0000 | - - | 57562 b |
EF 6 | Erste | Post | 310.55 US | 27.254 US | 45.799 US | 13.0000 | - - | - - | 43309 b |
EF -Kern | Erste | Post | 317.12 US | 1.354 US | 2.046 US | 3.5000 | - - | - - | 11306 b |
EF -Kern | SQLQuery | Post | 322.34 US | 23.990 US | 40.314 US | 5.0000 | - - | - - | 18195 b |
Nhibernate | Sql | Post | 325.54 US | 3.937 US | 7.527 US | 22.0000 | 1.0000 | - - | 80007 b |
EF 6 | "Zuerst (keine Verfolgung)" | Post | 331.14 US | 27.760 US | 46.649 US | 12.0000 | 1.0000 | - - | 50237 b |
EF -Kern | "Zuerst (keine Verfolgung)" | Post | 337.82 US | 27.814 US | 46.740 US | 3.0000 | 1.0000 | - - | 17986 b |
Nhibernate | Linq | Post | 604.74 US | 5.549 US | 10.610 US | 10.0000 | - - | - - | 46061 b |
Dapper Cache Impact | ExecuteParameters_Nocache | Leere | 623.42 US | 3.978 US | 6.684 US | 3.0000 | 2.0000 | - - | 10001 b |
Dapper Cache Impact | QueryFirstParameters_nocache | Leere | 630.77 US | 3.027 US | 4.576 US | 3.0000 | 2.0000 | - - | 10640 b |
Fühlen Sie sich frei, Patches mit anderen Ormen einzureichen. Wenn Sie Benchmarks ausführen, sollten Sie unbedingt in der Veröffentlichung kompilieren und keinen Debugger ( Strg + F5 ) anschließen.
Alternativ bevorzugen Sie Frans Boumas RawdataAccessBencher Test Suite oder Ormbenchmark.
Parameter werden normalerweise als anonyme Klassen übergeben. Auf diese Weise können Sie Ihre Parameter problemlos benennen und können SQL-Snippets einfach schneiden und pasten und im Query-Analysator Ihrer DB-Plattform ausführen.
new { A = 1 , B = " b " } // A will be mapped to the param @A, B to the param @B
Parameter können auch dynamisch mit der DynamicParameters -Klasse erstellt werden. Dies ermöglicht das Erstellen einer dynamischen SQL -Anweisung und verwendet gleichzeitig Parameter für Sicherheit und Leistung.
var sqlPredicates = new List < string > ( ) ;
var queryParams = new DynamicParameters ( ) ;
if ( boolExpression )
{
sqlPredicates . Add ( " column1 = @param1 " ) ;
queryParams . Add ( " param1 " , dynamicValue1 , System . Data . DbType . Guid ) ;
} else {
sqlPredicates . Add ( " column2 = @param2 " ) ;
queryParams . Add ( " param2 " , dynamicValue2 , System . Data . DbType . String ) ;
}
DynamicParameter unterstützt auch das Kopieren mehrerer Parameter aus vorhandenen Objekten verschiedener Typen.
var queryParams = new DynamicParameters ( objectOfType1 ) ;
queryParams . AddDynamicParams ( objectOfType2 ) ;
Wenn ein Objekt, das die IDynamicParameters
-Schnittstelle implementiert, in Execute
oder Query
übergeben wird, werden Parameterwerte über diese Schnittstelle extrahiert. Offensichtlich wäre die wahrscheinlichste Objektklasse für diesen Zweck die integrierte DynamicParameters
-Klasse.
Mit Dapper können Sie IEnumerable<int>
übergeben und Ihre Abfrage automatisch parametrisieren.
Zum Beispiel:
connection . Query < int > ( " select * from (select 1 as Id union all select 2 union all select 3) as X where Id in @Ids " , new { Ids = new int [ ] { 1 , 2 , 3 } } ) ;
Wird übersetzt in:
select * from ( select 1 as Id union all select 2 union all select 3 ) as X where Id in ( @Ids1 , @Ids2 , @Ids3 ) " // @Ids1 = 1 , @Ids2 = 2 , @Ids2 = 3
Dapper unterstützt den buchstäblichen Ersatz für Bool- und numerische Typen.
connection . Query ( " select * from User where UserTypeId = {=Admin} " , new { UserTypeId . Admin } ) ;
Der buchstäbliche Ersatz wird nicht als Parameter gesendet. Dies ermöglicht bessere Pläne und gefilterte Indexverbrauch, sollte jedoch normalerweise sparsam und nach dem Test verwendet werden. Diese Funktion ist besonders nützlich, wenn der injizierte Wert tatsächlich ein fester Wert ist (z. B. eine feste "Kategorie -ID", "Statuscode" oder "Region", die spezifisch für die Abfrage ist). Für Live- Daten, in denen Sie Literale in Betracht ziehen, möchten Sie möglicherweise auch Anbieter-spezifische Abfragen-Hinweise wie OPTIMIZE FOR UNKNOWN
mit regulären Parametern in Betracht ziehen und testen.
Das Standardverhalten von Dapper besteht darin, Ihren SQL auszuführen und den gesamten Leser bei der Rückkehr zu puffern. Dies ist in den meisten Fällen ideal, da die gemeinsam genutzten Sperren in der DB minimiert und die DB -Netzwerkzeit verkürzt werden.
Bei der Ausführung großer Abfragen müssen Sie jedoch möglicherweise den Speicher Fußabdruck minimieren und Objekte nach Bedarf nur laden. Um dies zu tun, buffered: false
in die Query
.
Mit Dapper können Sie eine einzelne Zeile mehrerer Objekte zuordnen. Dies ist eine wichtige Funktion, wenn Sie eine fremde Abfragebehörungen und eifrige Lastverbände vermeiden möchten.
Beispiel:
Betrachten Sie 2 Klassen: Post
und User
class Post
{
public int Id { get ; set ; }
public string Title { get ; set ; }
public string Content { get ; set ; }
public User Owner { get ; set ; }
}
class User
{
public int Id { get ; set ; }
public string Name { get ; set ; }
}
Nehmen wir nun an, dass wir eine Abfrage zuordnen möchten, die sich sowohl den Beiträgen als auch der Benutzertabelle anschließt. Bis jetzt müssten wir das Ergebnis von 2 Abfragen kombinieren, benötigen wir ein neues Objekt, um es auszudrücken, aber es ist in diesem Fall sinnvoller, das User
in das Post
zu stecken.
Dies ist der Anwendungsfall für Multi -Mapping. Sie sagen Dapper, dass die Abfrage einen Post
und ein User
zurückgibt, und geben ihm dann eine Funktion, die beschreibt, was Sie mit jedem der Zeilen mit einem Post
und einem User
tun möchten. In unserem Fall möchten wir das Benutzerobjekt nehmen und es in das Postobjekt einfügen. Also schreiben wir die Funktion:
( post , user ) => { post . Owner = user ; return post ; }
In den 3 -Typ -Argumenten für die Query
geben an, welche Objekte Dapper verwenden sollten, um die Zeile zu deserialisieren und was zurückgegeben wird. Wir werden beide Zeilen als eine Kombination aus Post
und User
interpretieren und ein Post
zurückgeben. Daher wird die Typdeklaration
< Post , User , Post >
Alles zusammengestellt, sieht so aus:
var sql =
@"select * from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id" ;
var data = connection . Query < Post , User , Post > ( sql , ( post , user ) => { post . Owner = user ; return post ; } ) ;
var post = data . First ( ) ;
Assert . Equal ( " Sams Post1 " , post . Content ) ;
Assert . Equal ( 1 , post . Id ) ;
Assert . Equal ( " Sam " , post . Owner . Name ) ;
Assert . Equal ( 99 , post . Owner . Id ) ;
Dapper ist in der Lage, die zurückgegebene Zeile zu teilen, indem Sie annehmen, dass Ihre ID -Spalten mit dem Namen Id
oder id
genannt werden. Wenn Ihr Primärschlüssel unterschiedlich ist oder Sie die Zeile an einem anderen Punkt als Id
teilen möchten, verwenden Sie den optionalen splitOn
-Parameter.
Mit Dapper können Sie mehrere Ergebnisgitter in einer einzelnen Abfrage verarbeiten.
Beispiel:
var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id" ;
using ( var multi = connection . QueryMultiple ( sql , new { id = selectedId } ) )
{
var customer = multi . Read < Customer > ( ) . Single ( ) ;
var orders = multi . Read < Order > ( ) . ToList ( ) ;
var returns = multi . Read < Return > ( ) . ToList ( ) ;
.. .
}
Dapper unterstützt gespeicherte Procs voll und ganz:
var user = cnn . Query < User > ( " spGetUser " , new { Id = 1 } ,
commandType : CommandType . StoredProcedure ) . SingleOrDefault ( ) ;
Wenn Sie etwas Locheres wollen, können Sie:
var p = new DynamicParameters ( ) ;
p . Add ( " @a " , 11 ) ;
p . Add ( " @b " , dbType : DbType . Int32 , direction : ParameterDirection . Output ) ;
p . Add ( " @c " , dbType : DbType . Int32 , direction : ParameterDirection . ReturnValue ) ;
cnn . Execute ( " spMagicProc " , p , commandType : CommandType . StoredProcedure ) ;
int b = p . Get < int > ( " @b " ) ;
int c = p . Get < int > ( " @c " ) ;
Dapper unterstützt VARCHAR -Parameter. Wenn Sie eine Where -Klausel in einer Varchar -Spalte mit einem Param ausführen, geben Sie diese auf diese Weise weiter:
Query < Thing > ( " select * from Thing where Name = @Name " , new { Name = new DbString { Value = " abcde " , IsFixedLength = true , Length = 10 , IsAnsi = true } } ) ;
Auf SQL Server ist es wichtig, den Unicode beim Abfrieren von Unicode und ANSI beim Abfragen von Nicht -Unicode zu verwenden.
Normalerweise möchten Sie alle Zeilen aus einer bestimmten Tabelle als denselben Datentyp behandeln. Es gibt jedoch einige Umstände, unter denen es nützlich ist, verschiedene Zeilen als unterschiedliche Datentypen analysieren zu können. Hier ist IDataReader.GetRowParser
nützlich.
Stellen Sie sich vor, Sie haben eine Datenbanktabelle mit dem Namen "Formen" mit den Spalten: Id
, Type
und Data
, und Sie möchten seine Zeilen in Circle
, Square
oder Triangle
analysieren, basierend auf dem Wert der Typ -Spalte.
var shapes = new List < IShape > ( ) ;
using ( var reader = connection . ExecuteReader ( " select * from Shapes " ) )
{
// Generate a row parser for each type you expect.
// The generic type <IShape> is what the parser will return.
// The argument (typeof(*)) is the concrete type to parse.
var circleParser = reader . GetRowParser < IShape > ( typeof ( Circle ) ) ;
var squareParser = reader . GetRowParser < IShape > ( typeof ( Square ) ) ;
var triangleParser = reader . GetRowParser < IShape > ( typeof ( Triangle ) ) ;
var typeColumnIndex = reader . GetOrdinal ( " Type " ) ;
while ( reader . Read ( ) )
{
IShape shape ;
var type = ( ShapeType ) reader . GetInt32 ( typeColumnIndex ) ;
switch ( type )
{
case ShapeType . Circle :
shape = circleParser ( reader ) ;
break ;
case ShapeType . Square :
shape = squareParser ( reader ) ;
break ;
case ShapeType . Triangle :
shape = triangleParser ( reader ) ;
break ;
default :
throw new NotImplementedException ( ) ;
}
shapes . Add ( shape ) ;
}
}
Um nicht-Parameter-SQL-Variablen mit MySQL Connector zu verwenden, müssen Sie Ihrer Verbindungszeichenfolge die folgende Option hinzufügen:
Allow User Variables=True
Stellen Sie sicher, dass Sie Dapper keine Eigenschaft zur Verfügung stellen.
Dapper speichert Informationen zu jeder Abfrage, die sie ausgeführt haben, und ermöglicht es ihm, Objekte schnell zu materialisieren und Parameter schnell zu verarbeiten. Die aktuelle Implementierung speichert diese Informationen in einem ConcurrentDictionary
Objekt. Aussagen, die nur einmal verwendet werden, werden aus diesem Cache routinemäßig gespült. Wenn Sie jedoch SQL -Zeichenfolgen im laufenden Fliegen ohne Parameter generieren, können Sie Speicherprobleme treffen.
Die Einfachheit von Dapper bedeutet, dass viele Merkmale, mit denen Orms geliefert werden, ausgezogen werden. Es macht sich um das 95% ige Szenario und gibt Ihnen die Werkzeuge, die Sie die meiste Zeit benötigen. Es versucht nicht, jedes Problem zu lösen.
Dapper hat keine dB -spezifischen Implementierungsdetails, es funktioniert in allen .NET -Ado -Anbietern, einschließlich SQLite, SQL CE, Firebird, Oracle, Mariadb, MySQL, PostgreSQL und SQL Server.
Dapper hat eine umfassende Testsuite im Testprojekt.
Dapper ist in der Produktion bei Stack Overflow in Produktion.