简体   繁体   中英

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 C RUD 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?

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);
    }
}

You can use only primitive types as parameters when inserting to table with Dapper.

You have at least following choices:

a) If Player-Rank-relation is One-to-One, you can refactor your class model so that Player-class contains all fields from your Rank-class and then remove your Rank class. Also you can modify your insert-clause to insert only to single Players-row with primitive types.

b) If Player-Rank-relation is One[Player]-to-Many[Ranks], you can refactor your solution by inserting Rank first (to it's own table, containing PlayerId as foreign key) and then Player object with it's fields.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM