2

In Dapper, what is the difference between the usage of QueryFirstOrDefault<T> and ExecuteScalar<T>?

Both seem to return a single value, although QueryFirstOrDefault<T> will return a default value for the type, if none is found. Should you always prefer the use of one of the two, due to performance, or other reasons, or are they equivalent, disregarding the default value returned?

SpiritBob
  • 2,355
  • 3
  • 24
  • 62

2 Answers2

6

The main difference is on their return:

ExecuteScalar<T>, as other users said, returns only the first cell of the result set.

  • The return type of ExecuteScalar<T> is generic <T>, and it automatically casts the result to the type you specified on <T>

QueryFirstOrDefault<T> executes a query and returns the data type you specified on <T>:

  • If the specified type is a basic type (string, int, etc...) it only returns the data from the first column.

  • If the specified type is an Object, then for each row of the result set an instance of that object is created. Be aware of the fact that a direct column-name===member-name mapping is assumed and no custom mapper can be used so if your object has different field names than the columns of the result set, no values will be fetched.

0

Scalar expects there to only be a single row returned from the SQL script; QueryFirstOrDefault doesn't care how many rows are returned.

I think (can't check this right now) that Scalar might throw an error if zero rows are returned (thanks @Tim for correcting me on multiple results).

I'd say the preference depends on what the script you've written is expected to do.

pete the pagan-gerbil
  • 3,136
  • 2
  • 28
  • 49
  • No error is generated if the result contains multiple rows. Internally, Dapper calls `IDbCommand.ExecuteScalar()`, which "Executes the query, and returns the first column of the first row in the resultset returned by the query. Extra columns or rows are ignored." Sources: [1](https://github.com/StackExchange/Dapper/blob/e47d819d4e3be933af97bde6b1b6f4f8c41fa534/Dapper/SqlMapper.cs) [2](https://learn.microsoft.com/en-us/dotnet/api/system.data.idbcommand.executescalar?view=netcore-3.1#System_Data_IDbCommand_ExecuteScalar) – MarredCheese Nov 06 '20 at 02:31