DapperLib / DapperLib/Dapper

IN clause doesn't support SqlMapper.TypeHandler

Open
#1,134 0 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
18.4k
Forks
3.7k
Avg merge
5h 8m
Merged PRs (30d)
1

Description

I'm using Dapper v1.50.5 from NuGet and I have this struct

public struct ItemGroupId : System.IEquatable<ItemGroupId>
{
  public static readonly ItemGroupId Empty = new ItemGroupId(0);

  private readonly int _value;

  public ItemGroupId(int value) => _value = value;

  public static explicit operator ItemGroupId(int value) => new ItemGroupId(value);

  public static explicit operator int(ItemGroupId value) => value._value;

  public override bool Equals(object obj) => obj is ItemGroupId ? this.Equals((ItemGroupId)obj) : false;

  public bool Equals(ItemGroupId other) => _value == other._value;

  public override int GetHashCode() => _value.GetHashCode();

  public static bool operator ==(ItemGroupId left, ItemGroupId right) => left.Equals(right);

  public static bool operator !=(ItemGroupId left, ItemGroupId right) => !(left == right);

  public override string ToString() => _value.ToString();
}

and this TypeHandler

public class ItemGroupIdTypeHandler : SqlMapper.TypeHandler<ItemGroupId>
{
  public override void SetValue(IDbDataParameter parameter, ItemGroupId value)
  {
    parameter.DbType = DbType.Int32;
    parameter.Value = value != ItemGroupId.Empty ? (object)(int)value : DBNull.Value;
  }

  public override ItemGroupId Parse(object value)
  {
    return new ItemGroupId((int?)value ?? 0);
  }
}

TypeHandler seems to work everywhere but when I try to use ItemGroupId in IN clause like this
sqb.Where("EXISTS (SELECT * FROM ItemForItemGroup WHERE ItemGroupId IN @ItemGroupIds AND ItemId = item.Id)", new { ItemGroupIds = sOptions.ItemGroupIds.ToList() });
I get error System.ArgumentException : No mapping exists from object type Removed.ItemGroupId to a known managed provider native type.

I had to change it to sqb.Where("EXISTS (SELECT * FROM ItemForItemGroup WHERE ItemGroupId IN @ItemGroupIds AND ItemId = item.Id)", new { ItemGroupIds = sOptions.ItemGroupIds.Select(x => (int)x).ToList() }); to make it work.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the IN-clause query with the ItemGroupId struct, its SqlMapper.TypeHandler, and the ItemGroupIds list shown in the issue. Trace parameter expansion and type-handler lookup for collection values; done means the handler is honored for each IN parameter without requiring conversion to int.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, sql
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.