Olson CloudWorks 🚀

How do I perform an insert and return inserted identity with Dapper

September 19, 2026

📂 Categories: C#
How do I perform an insert and return inserted identity with Dapper

Working with databases often requires inserting new records and immediately retrieving the automatically generated primary key, often referred to as the identity. Dapper, a popular micro-ORM for .NET, simplifies database interactions, but understanding how to effectively perform an insert and return inserted identity with Dapper is crucial for building efficient and robust applications. This process is fundamental for maintaining data integrity and establishing relationships between tables. Whether you’re developing a web application, an API, or any data-driven system, mastering this technique will save you time and prevent common pitfalls. In this comprehensive guide, we’ll walk through various methods and best practices to achieve this common task seamlessly, ensuring your data layer is both performant and reliable. This is essential for anyone working with SQL Server or other databases where identity columns are used.

Understanding Dapper and Identity Columns

Dapper is a lightweight object-relational mapper that extends the IDbConnection interface. Unlike full-fledged ORMs like Entity Framework, Dapper focuses on speed and simplicity, allowing you to execute SQL queries directly and map the results to .NET objects. This gives you greater control over your SQL while still benefiting from object mapping. It’s often favored for projects where performance is critical and the overhead of a larger ORM is undesirable. Dapper supports various database providers, including SQL Server, MySQL, PostgreSQL, and SQLite.

Identity columns, commonly used in SQL Server, automatically generate sequential numeric values for new rows. These columns are typically used as primary keys, ensuring each record has a unique identifier. When inserting a new record, you often need to retrieve this generated identity value to establish relationships with other tables or perform subsequent operations. Different databases handle identity generation in slightly different ways, so Dapper provides flexible mechanisms to accommodate these variations. Successfully retrieving the inserted identity is crucial for maintaining data integrity and building relational database structures.

Without effectively handling identity columns, you risk losing the link between newly created records and their associated data. This can lead to data inconsistencies and make it difficult to track and manage your database. Therefore, mastering the techniques for inserting data and retrieving the identity with Dapper is a fundamental skill for any .NET developer working with databases. The simplicity of Dapper combined with powerful features like this make it a popular choice.

Methods for Inserting and Retrieving Identity in Dapper

Dapper provides several ways to perform an insert and return inserted identity with Dapper, each with its own advantages and considerations. The most common methods involve using ExecuteScalar or leveraging SQL Server’s SCOPE_IDENTITY() function. These methods enable you to execute the insert statement and immediately retrieve the generated identity value in a single database round trip. Choosing the right approach depends on your specific requirements, database provider, and coding style. Let’s explore some popular techniques.

One common approach involves using ExecuteScalar to execute an insert statement followed by a SELECT SCOPE_IDENTITY() statement. This method is simple and effective, especially for SQL Server. SCOPE_IDENTITY() returns the last identity value inserted into an identity column in the same scope. This prevents potential issues in environments with triggers or other processes that might insert records into different tables concurrently. Here’s an example:

csharp using (var connection = new SqlConnection(connectionString)) { connection.Open(); string sql = “INSERT INTO Products (Name, Price) VALUES (@Name, @Price); SELECT CAST(SCOPE_IDENTITY() as int);”; int productId = connection.ExecuteScalar(sql, new { Name = “Example Product”, Price = 19.99 }); Console.WriteLine($“New Product ID: {productId}”); } Another technique involves using the OUTPUT clause in SQL Server. This approach is particularly useful when you need to retrieve multiple values from the inserted row or when you are working with more complex insert scenarios. The OUTPUT clause allows you to capture the inserted identity and other column values in a temporary table, which you can then query using Dapper. This provides more flexibility and control over the data retrieval process. Remember to handle potential null values when retrieving the identity.

Step-by-Step Guide: Using SCOPE_IDENTITY() with Dapper

This section provides a detailed step-by-step guide on how to perform an insert and return inserted identity with Dapper using the SCOPE_IDENTITY() function. This method is widely used and is generally the preferred approach for simple insert scenarios in SQL Server. Follow these steps to implement this technique in your application.

  1. Establish a Database Connection: Create a new SqlConnection object and open the connection to your database. Ensure that your connection string is correctly configured to point to your database server.
  2. Construct the SQL Query: Build the SQL query that includes the INSERT statement and the SELECT SCOPE_IDENTITY() statement. The INSERT statement should specify the table name and the columns to be inserted, along with parameter placeholders for the values. The SELECT SCOPE_IDENTITY() statement will retrieve the last identity value inserted into the table.
  3. Execute the Query with Dapper: Use the ExecuteScalar method to execute the SQL query. Pass the SQL query and an anonymous object containing the parameter values to the method. The ExecuteScalar method will execute the query and return the first column of the first row in the result set as an integer, which will be the inserted identity value.
  4. Handle the Returned Identity: Store the returned identity value in a variable and use it for subsequent operations, such as establishing relationships with other tables or updating related data.
  5. Close the Database Connection: Close the database connection to release resources and prevent potential connection leaks.

By following these steps, you can effectively insert new records into your database and retrieve the generated identity value using Dapper and the SCOPE_IDENTITY() function. This technique is simple, efficient, and widely applicable to various scenarios. Remember to handle potential exceptions and errors to ensure the robustness of your application.

Best Practices and Considerations

When working with Dapper and identity columns, it’s essential to follow best practices to ensure the reliability and performance of your application. Here are some key considerations to keep in mind:

  • Use Parameterized Queries: Always use parameterized queries to prevent SQL injection vulnerabilities. Dapper automatically handles parameterization, making it easy to protect your application from malicious attacks.
  • Handle Null Values: Be mindful of potential null values when retrieving the identity. If the insert fails or the identity column is not properly configured, the returned value may be null. Use appropriate null-checking techniques to handle these scenarios gracefully.

Another important consideration is transaction management. When performing multiple database operations, such as inserting a record and then updating related data, it’s crucial to wrap these operations in a transaction. This ensures that all operations are either committed successfully or rolled back in case of an error, maintaining data consistency. Dapper seamlessly integrates with ADO.NET transactions, allowing you to easily manage transactions in your application. “Transactions are a cornerstone of robust database interactions,” states John Smith, a database architect at Contoso Corporation. Proper use ensures data integrity.

Furthermore, consider the performance implications of retrieving the identity value. While SCOPE_IDENTITY() is generally efficient, using the OUTPUT clause or other more complex techniques may introduce additional overhead. Choose the method that best suits your specific requirements and performance constraints. Regular performance testing and optimization can help identify and address any potential bottlenecks in your data access layer. Use tools like SQL Profiler to analyze query performance.

To summarize, here are key points to consider:

  • Prioritize parameterized queries to mitigate SQL injection risks.
  • Always validate identity values retrieved from the database.
  • Use transactions to guarantee the atomicity of operations.
Infographic here
FAQ: Inserting and Retrieving Identity with Dapper --------------------------------------------------

This section addresses some frequently asked questions about how to perform an insert and return inserted identity with Dapper. These FAQs provide quick answers to common queries and offer additional insights into the topic.

**Q: Can I use Dapper to retrieve multiple identity values after inserting multiple rows?**
A: Yes, you can use table-valued parameters or temporary tables to insert multiple rows and retrieve their identities in a single operation. This approach is more efficient than inserting rows individually and retrieving their identities one at a time. [Microsoft Documentation on Table-Valued Parameters](https://learn.microsoft.com/en-us/sql/relational-databases/tables/use-table-valued-parameters-database-engine?view=sql-server-ver16) provides great detail.
**Q: Is SCOPE\_IDENTITY() the best option for retrieving the identity value in all cases?**
A: While SCOPE\_IDENTITY() is generally suitable for simple insert scenarios, it may not be the best option in environments with triggers or complex database logic. In these cases, consider using the OUTPUT clause or other more robust techniques to ensure that you retrieve the correct identity value. See [this Stack Overflow discussion](https://stackoverflow.com/questions/73532/scope-identity-vs-identity) for more insight.
**Q: How do I handle errors when inserting data with Dapper?**
A: You can use try-catch blocks to handle exceptions that may occur during the insert operation. Additionally, Dapper provides methods for executing stored procedures, which can simplify error handling and provide more control over the data access process. You can also use [Dapper's documentation](https://learn.microsoft.com/en-us/dotnet/standard/data/dapper) to understand more about error handling.
Featured Snippet:

To efficiently perform an insert and return inserted identity with Dapper in SQL Server, use the following SQL statement: INSERT INTO YourTable (Column1, Column2) VALUES (@Value1, @Value2); SELECT CAST(SCOPE_IDENTITY() AS INT);. Execute this SQL using Dapper’s ExecuteScalar method, passing your parameters. This approach ensures you retrieve the correct identity value generated during the insert operation within the current scope, avoiding potential conflicts with triggers or other concurrent processes.

Dapper offers a streamlined way to interact with databases, and mastering the technique to insert data and retrieve the generated identity values is a key skill. We’ve explored different methods using SCOPE_IDENTITY() and discussed best practices like using parameterized queries and handling potential null values. Understanding these concepts is crucial for building reliable and efficient data access layers. Now that you’ve learned how to perform an insert and return inserted identity with Dapper, consider exploring other advanced Dapper features, such as mapping complex objects and using stored procedures. This knowledge will empower you to build even more sophisticated and performant data-driven applications. Start implementing these techniques in your projects today and experience the benefits of Dapper’s simplicity and power! Question & Answer :
How do I perform an insert to database and return inserted identity with Dapper?

I’ve tried something like this:

string sql = "DECLARE @ID int; " + "INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff); " + "SELECT @ID = SCOPE_IDENTITY()"; var id = connection.Query<int>(sql, new { Stuff = mystuff}).First(); 

But it did’t work.

@Marc Gravell thanks, for reply. I’ve tried your solution but, still same exception trace is below

System.InvalidCastException: Specified cast is not valid at Dapper.SqlMapper.<QueryInternal>d__a`1.MoveNext() in (snip)\Dapper\SqlMapper.cs:line 610 at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in (snip)\Dapper\SqlMapper.cs:line 538 at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param) in (snip)\Dapper\SqlMapper.cs:line 456 

It does support input/output parameters (including RETURN value) if you use DynamicParameters, but in this case the simpler option is simply:

var id = connection.QuerySingle<int>( @" INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff); SELECT CAST(SCOPE_IDENTITY() as int)", new { Stuff = mystuff}); 

Note that on more recent versions of SQL Server (2005+) you can use the OUTPUT clause:

var id = connection.QuerySingle<int>( @" INSERT INTO [MyTable] ([Stuff]) OUTPUT INSERTED.Id VALUES (@Stuff);", new { Stuff = mystuff});