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