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