### Example Dapper Product Query Source: https://aot.dapperlib.dev/gettingstarted A C# example demonstrating a typical Dapper query to retrieve a single product by its ID. ```csharp public class Product { public static Product GetProduct(SqlConnection connection, int productId) => connection.QueryFirst( "select * from Production.Product where ProductId=@productId", new { productId }); public int ProductID { get; set; } public string Name { get; set; } public string ProductNumber { get; set; } // etc ``` -------------------------------- ### Building a Project with Dapper.AOT Source: https://aot.dapperlib.dev/gettingstarted Example output from the dotnet build command showing a DAP219 warning. ```txt > dotnet build MSBuild version 17.8.3+195e7f5a3 for .NET Determining projects to restore... All projects are up-to-date for restore. C:\Code\DapperAOT\test\UsageLinker\Product.cs(16,17): warning DAP219: SELECT columns should be specified explicitly (https://aot.dapperlib.dev/rules/DAP219) [C:\Code\DapperAOT\test\UsageLinker\UsageLinker.csproj] ``` -------------------------------- ### Check .NET SDK Version Source: https://aot.dapperlib.dev/gettingstarted Use the `dotnet --info` command to verify your installed .NET SDK version. Dapper.AOT requires .NET 8 or later. ```txt > dotnet --info .NET SDK: Version: 8.0.100 (snip lots more here) ``` -------------------------------- ### Add Dapper.AOT NuGet Package via CLI Source: https://aot.dapperlib.dev/gettingstarted Install the Dapper.AOT package using the .NET CLI command. ```txt > dotnet add package Dapper.AOT ``` -------------------------------- ### Add Dapper and Microsoft.Data.SqlClient NuGet Packages Source: https://aot.dapperlib.dev/gettingstarted Include these packages in your project file to use Dapper and SQL Server connectivity. ```xml ``` -------------------------------- ### Querying a Product with Dapper.AOT Source: https://aot.dapperlib.dev/gettingstarted Demonstrates a basic query using SqlConnection. The analyzer will flag the use of 'select *' in this context. ```csharp public static Product GetProduct(SqlConnection connection, int productId) => connection.QueryFirst( "select * from Production.Product where ProductId=@productId", new { productId }); ``` -------------------------------- ### Implement a RowFactory for Product Source: https://aot.dapperlib.dev/generatedcode A custom RowFactory implementation that maps database columns to a Product object using Tokenize for column identification and Read for data population. ```csharp private sealed class RowFactory0 : global::Dapper.RowFactory { internal static readonly RowFactory0 Instance = new(); private RowFactory0() {} public override object? Tokenize(global::System.Data.Common.DbDataReader reader, global::System.Span tokens, int columnOffset) { for (int i = 0; i < tokens.Length; i++) { int token = -1; var name = reader.GetName(columnOffset); var type = reader.GetFieldType(columnOffset); switch (NormalizedHash(name)) { case 2521315361U when NormalizedEquals(name, "productid"): token = type == typeof(int) ? 0 : 25; // two tokens for right-typed and type-flexible break; case 2369371622U when NormalizedEquals(name, "name"): token = type == typeof(string) ? 1 : 26; break; // snip, more columns here } tokens[i] = token; columnOffset++; } return null; } public override global::UsageLinker.Product Read(global::System.Data.Common.DbDataReader reader, global::System.ReadOnlySpan tokens, int columnOffset, object? state) { global::UsageLinker.Product result = new(); foreach (var token in tokens) { switch (token) { case 0: result.ProductID = reader.GetInt32(columnOffset); break; case 25: result.ProductID = GetValue(reader, columnOffset); break; case 1: result.Name = reader.GetString(columnOffset); break; case 26: result.Name = GetValue(reader, columnOffset); break; // snip, more columns here } columnOffset++; } return result; } } ``` -------------------------------- ### Enable Dapper.AOT Globally with Module Attribute Source: https://aot.dapperlib.dev/gettingstarted Apply the `[module:DapperAot]` attribute in any C# file to enable Dapper.AOT for the entire project. This is a convenient way to opt-in. ```csharp [module:DapperAot] ``` -------------------------------- ### Enable Dapper.AOT Globally Source: https://aot.dapperlib.dev/rules/DAP005 Add this attribute to your AssemblyInfo.cs file to enable Dapper.AOT for your entire project. This is the most common way to enable it. ```csharp [module: DapperAot] ``` -------------------------------- ### Add Dapper.AOT NuGet Package via Project File Source: https://aot.dapperlib.dev/gettingstarted Alternatively, add the Dapper.AOT package reference directly to your project file. ```xml ``` -------------------------------- ### Bulk Copy with SqlBulkCopy and TypeAccessor Source: https://aot.dapperlib.dev/bulkcopy Efficiently write data from a sequence of objects to a SQL Server table using SqlBulkCopy and TypeAccessor. Specify column mappings and restrict exposed properties for optimized performance. ```csharp using var table = new SqlBulkCopy(connection) { DestinationTableName = "Customers", ColumnMappings = { { nameof(Customer.CustomerNumber), nameof(Customer.CustomerNumber) } { nameof(Customer.Name), nameof(Customer.Name) } } }; table.EnableStreaming = true; table.WriteToServer(TypeAccessor.CreateDataReader(customers, [nameof(Customer.Name), nameof(Customer.CustomerNumber)])); return table.RowsCopied; ``` -------------------------------- ### Avoid SELECT * in SQL Queries Source: https://aot.dapperlib.dev/rules/DAP219 Using SELECT * can lead to performance issues by fetching unnecessary columns and unpredictable column order. Always specify the columns you need. ```sql select * from SomeTable ``` ```sql select Id, Name, Description from SomeTable ``` -------------------------------- ### Implement a CommandFactory for ADO.NET parameters Source: https://aot.dapperlib.dev/generatedcode This factory handles parameter creation and updates for anonymous types by casting the input and using the UnifiedCommand API. ```csharp private sealed class CommandFactory0 : global::Dapper.CommandFactory // { internal static readonly CommandFactory0 Instance = new(); public override void AddParameters(in global::Dapper.UnifiedCommand cmd, object? args) { var typed = Cast(args, static () => new { productId = default(int) }); // expected shape var ps = cmd.Parameters; global::System.Data.Common.DbParameter p; p = cmd.CreateParameter(); p.ParameterName = "productId"; p.DbType = global::System.Data.DbType.Int32; p.Direction = global::System.Data.ParameterDirection.Input; p.Value = AsValue(typed.productId); ps.Add(p); } public override void UpdateParameters(in global::Dapper.UnifiedCommand cmd, object? args) { var typed = Cast(args, static () => new { productId = default(int) }); // expected shape var ps = cmd.Parameters; ps[0].Value = AsValue(typed.productId); } public override bool CanPrepare => true; } ``` -------------------------------- ### Enable Interceptors Preview Feature Source: https://aot.dapperlib.dev/gettingstarted Configure your project file to opt-in to the 'interceptors' experimental feature, which is required by Dapper.AOT. This allows code generation in the Dapper.AOT namespace. ```xml $(InterceptorsPreviewNamespaces);Dapper.AOT ``` -------------------------------- ### Good SQL INSERT Statement with Explicit Columns Source: https://aot.dapperlib.dev/rules/DAP216 This is the recommended way to perform INSERT operations. Explicitly listing columns ensures the data is inserted into the correct fields, regardless of column order. ```sql insert SomeTable (SomeColumn) values (42) ``` -------------------------------- ### Create DbDataReader from IEnumerable Source: https://aot.dapperlib.dev/bulkcopy Use TypeAccessor.CreateDataReader to convert a sequence of objects into a DbDataReader. This is useful for preparing data for bulk copy operations. ```csharp IEnumerable customers = ... var reader = TypeAccessor.CreateDataReader(customers); ``` -------------------------------- ### Corrected Product Query Source: https://aot.dapperlib.dev/gettingstarted An updated version of the query that specifies columns explicitly to satisfy the DAP219 rule. ```csharp public static Product GetProduct(SqlConnection connection, int productId) => connection.QueryFirst( "select ProductID, Name, ProductNumber from Production.Product where ProductId=@productId", new { productId }); ``` -------------------------------- ### Bad SQL INSERT Statement Source: https://aot.dapperlib.dev/rules/DAP216 Avoid this pattern as it relies on implicit column order, which can vary between database environments. Use explicit column names instead. ```sql insert SomeTable values (42) ``` -------------------------------- ### Source Code Method Call Source: https://aot.dapperlib.dev/generatedcode The original Dapper method call in the user's source code that triggers the AOT generation. ```csharp public static Product GetProduct(DbConnection connection, int productId) => connection.QueryFirst( "select * from Production.Product where ProductId=@productId", new { productId }); ``` -------------------------------- ### Generated Interceptor Method Source: https://aot.dapperlib.dev/generatedcode The generated interceptor method that replaces the original call using the InterceptsLocationAttribute. ```csharp [global::System.Runtime.CompilerServices.InterceptsLocationAttribute("C:\\Code\\DapperAOT\\test\\UsageLinker\\Product.cs", 14, 92)] internal static global::UsageLinker.Product QueryFirst1(this global::System.Data.IDbConnection cnn, string sql, object? param, global::System.Data.IDbTransaction? transaction, int? commandTimeout, global::System.Data.CommandType? commandType) { // Query, TypedResult, HasParameters, SingleRow, Text, AtLeastOne, BindResultsByName, KnownParameters // takes parameter: // parameter map: productId // returns data: global::UsageLinker.Product global::System.Diagnostics.Debug.Assert(!string.IsNullOrWhiteSpace(sql)); global::System.Diagnostics.Debug.Assert((commandType ?? global::Dapper.DapperAotExtensions.GetCommandType(sql)) == global::System.Data.CommandType.Text); global::System.Diagnostics.Debug.Assert(param is not null); return global::Dapper.DapperAotExtensions.Command(cnn, transaction, sql, global::System.Data.CommandType.Text, commandTimeout.GetValueOrDefault(), CommandFactory0.Instance).QueryFirst(param, RowFactory0.Instance); } ``` -------------------------------- ### Disable Dapper.AOT Globally Source: https://aot.dapperlib.dev/rules/DAP005 Use this attribute to disable Dapper.AOT for your entire project. This is useful if you want to selectively enable it in specific areas. ```csharp [module: DapperAot(false)] ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.