Search code examples
c#databasesqlitedapper

Can't use custom type as parameter in Dapper query to insert into SQLite Database


I have a Player class which has an Id, Username and Rank:

class Player
{
    public int Id { get; set; }
    public string Username { get; set; }
    public Rank Rank { get; set; }
}

I want to insert a new player to an SQLite database, to do this I'm using Dapper.

On form button press:

Player newPlayer = new Player();
Rank newRank = new Rank();
newPlayer.Username = txtUsername.Text;
newPlayer.Rank = newRank;

if (newPlayer.Username != null && newPlayer.Username != String.Empty)
{               
    SQLiteDataAccess.SavePlayer(newPlayer);
    Close();
}

My CRUD method in "SQLiteDataAccess"

public static void SavePlayer(Player player)
{
    using (IDbConnection connection = new SQLiteConnection(LoadConnectionString()))
    {
        connection.Execute("insert into Players (Username, Rank) values (@Username, @Rank)",
                           player);
    }
}


My "Rank" class consists of a string name, and a few integers. I have a constructor that sets them all to default values of "-" and 0.

There is a problem when I use this custom "Rank" type as a parameter:

System.NotSupportedException: 'The member Rank of type Prototype1.Rank cannot be used as a parameter value'

Is there a way around this, or another way without using Dapper?


Solution

  • First of all, use string.IsNullOrEmpty() instead of doing if (newPlayer.Username != null && newPlayer.Username != String.Empty).

    Dapper itself don't do this kind of insert. You need to add you rank class first and bind the id to a value type RankID in your Player class. For example:

    public class Player
    {
        public int Id { get; set; }
        public string Username { get; set; }
        public int RankId { get; set; }
        public Rank Rank { get; set; }
    }
    
    public class Rank
    {
        public int Id { get; set; }
        public string Something { get; set; }
    }
    
    public class Repo
    {
        public void Save(Player player)
        {
            // .. open connection
            player.RankId = connection.ExecuteScalar<int>("insert into Rank (Something) values (@Something)", player.Rank);
            player.Id = connection.ExecuteScalar<int>("insert into Player (Username, RankId) values (@Username, @RankId", player);
        }
    }