Я использую наследование базы данных по иерархии таблиц, где столбцы для всех производных типов находятся в одной таблице. Каждая производная таблица идентифицируется с помощью строкового поля Discriminator, которое содержит имя производного класса:
---------------------
| tanimal |
---------------------
| animalid |
| discriminator |
| furcolour |
| feathercolour |
---------------------
public abstract class Animal
{
public int AnimalId { get; set; }
public string Discriminator { get { return GetType().Name; } }
}
public class Bird : Animal
{
public string FeatherColour { get; set; }
}
public class Dog : Animal
{
public string FurColour { get; set; }
}
Как и ожидалось, при получении этого с помощью метода запроса Dapper я получаю Instances of abstract classes cannot be created
. Я надеюсь, что это вернет список Animal с их значениями, являющимися соответствующими производными типами.
var animals = Connection.Query<Animal>("SELECT * FROM tanimal")
Мои попытки добавить поддержку для этого не увенчались успехом. Перед вызовом SqlMapper.cs :: GetTypeDeserializer (), если передаваемый тип является абстрактным классом, я заменяю тип на тип, возвращенный следующим методом:
static Type GetDerivedType(Type abstractType, IDataReader reader)
{
var discriminator = abstractType.GetProperty("Discriminator");
if (discriminator == null)
throw new InvalidOperationException("Cannot create instance of abstract class " + abstractType.FullName + ". To allow dapper to map to a derived type, add a Discriminator field that stores the name of the derived type");
return Type.GetType((string)reader["Discriminator"]);
}
Однако похоже, что на данный момент программа чтения еще не открыта, поэтому она не работает с Invalid attempt to read when no data is present
.
Это правильный подход? Были ли какие-либо усилия поддержать это где-то еще?