如何优雅映射数据库VARCHAR到读模型的IEnumerable<bool>属性
解决方案:VARCHAR字符串转IEnumerable映射
我来分享几个简便优雅的实现方式,刚好我之前也处理过类似的数据库字段映射需求:
方案1:自定义JsonConverter(适合序列化/反序列化场景)
如果你的读模型需要通过Json序列化来完成转换,自定义Json转换器是个不错的选择,比直接用默认的JsonConvert特性更灵活:
首先创建一个自定义转换器:
public class StringToBoolEnumerableConverter : JsonConverter<IEnumerable<bool>> { public override IEnumerable<bool> ReadJson(JsonReader reader, Type objectType, IEnumerable<bool> existingValue, bool hasExistingValue, JsonSerializer serializer) { var str = reader.Value?.ToString(); if (string.IsNullOrEmpty(str)) return Enumerable.Empty<bool>(); // 去除括号,分割字符串,转换为bool return str.Trim('(', ')') .Split(',') .Select(s => bool.Parse(s.Trim())); } public override void WriteJson(JsonWriter writer, IEnumerable<bool> value, JsonSerializer serializer) { // 反向转换,把bool集合转成数据库需要的字符串格式 var strValues = value.Select(b => b.ToString().ToUpperInvariant()); writer.WriteValue($"({string.Join(",", strValues)})"); } }
然后在你的模型属性上标记这个转换器:
public class MyClass { [JsonConverter(typeof(StringToBoolEnumerableConverter))] public IEnumerable<bool> MyList { get; set; } }
方案2:EF Core ValueConverter(直接数据库映射)
如果是通过EF Core读取数据库数据,我更推荐用ValueConverter,它能直接在数据访问层完成转换,读模型本身不用加任何特性,更干净:
在你的DbContext的OnModelCreating方法里配置映射:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<MyClass>() .Property(e => e.MyList) .HasConversion( // 把IEnumerable<bool>转成数据库存储的字符串 v => $"({string.Join(",", v.Select(b => b.ToString().ToUpperInvariant()))})", // 把数据库的字符串转成IEnumerable<bool> v => v.Trim('(', ')') .Split(',') .Select(s => bool.Parse(s.Trim())) ) .HasColumnType("varchar"); // 指定数据库字段类型 }
这样EF Core在读取和写入数据时会自动完成转换,你的读模型只需要保留IEnumerable<bool>属性即可:
public class MyClass { public IEnumerable<bool> MyList { get; set; } }
方案3:手动解析扩展方法(灵活轻量)
如果不想依赖序列化框架或EF Core,写个扩展方法手动解析也很方便:
public static class StringExtensions { public static IEnumerable<bool> ToBoolEnumerable(this string str) { if (string.IsNullOrWhiteSpace(str)) return Enumerable.Empty<bool>(); return str.Trim('(', ')') .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(s => bool.TryParse(s.Trim(), out var result) ? result : false); } }
使用的时候可以在模型里用私有字段存储原始字符串,公开属性返回转换后的集合:
public class MyClass { // 对应数据库的VARCHAR字段 private string _myListStr { get; set; } public IEnumerable<bool> MyList => _myListStr.ToBoolEnumerable(); }
或者在读取数据后手动调用扩展方法转换:
// 假设从数据库读取到原始字符串 var dbStr = "(FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE)"; var boolList = dbStr.ToBoolEnumerable();
内容的提问来源于stack exchange,提问作者maskedmenace
相关产品推荐
相关产品推荐

