Dapper 在继承层次结构中处理数据
Dapper 包含一项功能,用于处理可能逐行映射到不同类型的数据。在处理使用Table Per Hierarchy存储模式的继承层次结构时,此功能特别有用,即一个表用于表示层次结构中的所有类。“鉴别器”列用于区分类型。
以下类定义表示基于抽象Contract类型的继承层次结构。还定义了三种派生类型,代表通信/媒体业务提供的不同类型的合同。该ContractType属性充当鉴别器。
public abstract class Contract
{
public int ContractId { get; set; }
public DateTime StartDate { get; set; }
public int DurationMonths { get; set;}
public decimal Charge { get; set; }
public ContractType ContractType { get; set; }
public int CustomerId { get; set; }
}
public class MobileContract : Contract
{
public MobileContract() => ContractType = ContractType.Mobile;
public string MobileNumber { get; set; }
}
public class TvContract : Contract
{
public TvContract() => ContractType = ContractType.TV;
public TVPackageType TVPackageType { get; set; }
}
public class BroadBandContract : Contract
{
public BroadBandContract() => ContractType = ContractType.Broadband;
public int DownloadSpeed { get; set; }
}
public enum TVPackageType
{
S, M, L, XL
}
public enum ContractType
{
Mobile = 1, TV, Broadband
}
这些类映射到具有以下架构(SQLite)的单个表:

以下代码显示了如何使用ExecuteReader和GetRowsParser<T>方法根据当前正在读取的合约类型填充三个集合:
var tvContracts = new List<TvContract>();
var mobileContracts = new List<MobileContract>();
var broadbandContracts = new List<BroadbandContract>();
var sql = @"select * from contracts";
using (var connection = new SQLiteConnection(connString))
using (var reader = connection.ExecuteReader(sql))
{
var tvContractParser = reader.GetRowParser<TvContract>();
var mobileContractParser = reader.GetRowParser<MobileContract>();
var broadbandContractParser = reader.GetRowParser<BroadbandContract>();
while(reader.Read())
{
var discriminator = (ContractType)reader.GetInt32(reader.GetOrdinal(nameof(ContractType)));
switch(discriminator)
{
case ContractType.TV:
tvContracts.Add(tvContractParser(reader));
break;
case ContractType.Broadband:
broadbandContracts.Add(broadbandContractParser(reader));
break;
case ContractType.Mobile:
mobileContracts.Add(mobileContractParser(reader));
break;
}
}
}
Console.WriteLine("TV Contracts");
tvContracts.ForEach(c => Console.WriteLine($"Duration: {c.DurationMonths} months, Package Type: {c.TVPackageType.ToString()}"));
Console.WriteLine("Broadband Contracts");
broadbandContracts.ForEach(c => Console.WriteLine($"Duration: {c.DurationMonths} months, Cost: {c.Charge}, Download: {c.DownloadSpeed} Mbps"));
Console.WriteLine("Mobile Contracts");
mobileContracts.ForEach(c => Console.WriteLine($"Duration: {c.DurationMonths} months, Number: {c.MobileNumber}"));

浙公网安备 33010602011771号