Base type:
public class TreeRecord
{
public long id;
public long? parent_id;
}
Record type:
public class TestRecord : TreeRecord
{
public string name;
}
Using Dapper to inset will fail, because it can't find the values. I suspect that is because some of the fields are from the base type.
public long Add(T record, bool returnIndex = false)
{
var query =
$"INSERT INTO {TableName} ({string.Join(", ", _fields)}, parent_id) " +
$"VALUES (@{string.Join(", @", _fields)}, @parent_id);";
// Seems like Dapper won't flatten this type hierachy.
_connection.Execute(query, record);
}
I'm working in a generic container, where T inherits from TR and "extends" the fields. Because of this, I can't simply provide a flattened new ... construct for the value parameters for Dapper. _fields are non-base fields in T, in this case just name from TestRecord.
The exception thrown is:
System.InvalidOperationException: Must add values for the following parameters: @name, @parent_id
even though both are set (p_id to null, name to Books) (inside Dapper's Execute):

Is it a flattening issue? IMO, because all fields on a TestRecord, including the base fields, can be accessed by var.field, Dapper should be able to use it.
The behavior you're seeing here is because ultimately Dapper is looking for properties and not fields. Underneath the covers, it's calling typeof(RecordType).GetProperties(); and enumerating them for the dynamic parameter generation.
If you change your types to:
public class TreeRecord
{
public long id { get; set; }
public long? parent_id { get; set; }
}
public class TestRecord : TreeRecord
{
public string name { get; set; }
}
...then you should see it working, on base or inherited types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With