CsvHelper 忽略复杂类型
CsvHelper Ignore Complex Types
我正在尝试将 CSV 文件中的测试数据加载到可以加载到内存中 EF 核心数据库上下文中的记录中。
我有一个简化后的实体:
public class Project
{
public int { get; set; }
public Owner? Owner { get; set; } = null;
}
一个class地图:
public class ProjectsClassMap : CsvHelper.Configuration.ClassMap<Projects>
{
public ProjectsClassMap()
{
AutoMap(CultureInfo.CurrentCulture);
Map(m => m.Owner).Ignore();
}
}
然后像这样加载数据的函数:
private void LoadTestData<T>(string fileName, InMemoryEFCoreDbContext db, Type? classMap = null)
where T : class
{
var data = GetTestData(fileName);
var readerConfig = new CsvConfiguration(CultureInfo.CurrentCulture) {
Delimiter = ",",
PrepareHeaderForMatch = (r, c) => r.Replace(" ", string.Empty).ToLower(),
MissingFieldFound = (string[] values, int index, ReadingContext context) => { },
ReadingExceptionOccurred = (ex) => false,
HeaderValidated = (isValid, headerNames, headerNameIndex, context) => { },
HasHeaderRecord = true,
UseNewObjectForNullReferenceMembers = true,
};
if(classMap != null)
{
readerConfig.RegisterClassMap(classMap);
readerConfig.IgnoreReferences = true;
}
using (var sReader = new StringReader(data))
using (var csvReader = new CsvHelper.CsvReader(sReader, readerConfig))
{
var records = csvReader.GetRecords<T>().ToList();
db.Set<T>().AddRange(records);
db.SaveChanges();
}
}
问题是 Owner 设置为新值而不是默认值 null,这会在尝试保存到 DbContext 时导致验证错误。如何将复杂引用类型保留为 null 而不是 new?
试试这个
public class ProjectsClassMap : CsvHelper.Configuration.ClassMap<Project>
{
public ProjectsClassMap()
{
var config = new CsvConfiguration(CultureInfo.CurrentCulture)
{
IgnoreReferences = true
};
AutoMap(config);
}
}
来自@JoshClose 的更新
The issue here is that AutoMap will set up all properties down the tree and ignoring that property doesn't remove all the properties on Owner.
使用不带 ProjectsClassMap
的 [Ignore]
属性,AutoMap
将正确设置它。
public class Project
{
public int { get; set; }
[Ignore]
public Owner? Owner { get; set; } = null;
}
或者,如果您需要使用 class 地图,则必须手动删除引用。
public class ProjectsClassMap : CsvHelper.Configuration.ClassMap<Project>
{
public ProjectsClassMap()
{
AutoMap(CultureInfo.CurrentCulture);
ReferenceMaps.Remove(ReferenceMaps.Find<Project>(m => m.Owner));
}
}
我正在尝试将 CSV 文件中的测试数据加载到可以加载到内存中 EF 核心数据库上下文中的记录中。
我有一个简化后的实体:
public class Project
{
public int { get; set; }
public Owner? Owner { get; set; } = null;
}
一个class地图:
public class ProjectsClassMap : CsvHelper.Configuration.ClassMap<Projects>
{
public ProjectsClassMap()
{
AutoMap(CultureInfo.CurrentCulture);
Map(m => m.Owner).Ignore();
}
}
然后像这样加载数据的函数:
private void LoadTestData<T>(string fileName, InMemoryEFCoreDbContext db, Type? classMap = null)
where T : class
{
var data = GetTestData(fileName);
var readerConfig = new CsvConfiguration(CultureInfo.CurrentCulture) {
Delimiter = ",",
PrepareHeaderForMatch = (r, c) => r.Replace(" ", string.Empty).ToLower(),
MissingFieldFound = (string[] values, int index, ReadingContext context) => { },
ReadingExceptionOccurred = (ex) => false,
HeaderValidated = (isValid, headerNames, headerNameIndex, context) => { },
HasHeaderRecord = true,
UseNewObjectForNullReferenceMembers = true,
};
if(classMap != null)
{
readerConfig.RegisterClassMap(classMap);
readerConfig.IgnoreReferences = true;
}
using (var sReader = new StringReader(data))
using (var csvReader = new CsvHelper.CsvReader(sReader, readerConfig))
{
var records = csvReader.GetRecords<T>().ToList();
db.Set<T>().AddRange(records);
db.SaveChanges();
}
}
问题是 Owner 设置为新值而不是默认值 null,这会在尝试保存到 DbContext 时导致验证错误。如何将复杂引用类型保留为 null 而不是 new?
试试这个
public class ProjectsClassMap : CsvHelper.Configuration.ClassMap<Project>
{
public ProjectsClassMap()
{
var config = new CsvConfiguration(CultureInfo.CurrentCulture)
{
IgnoreReferences = true
};
AutoMap(config);
}
}
来自@JoshClose 的更新
The issue here is that AutoMap will set up all properties down the tree and ignoring that property doesn't remove all the properties on Owner.
使用不带 ProjectsClassMap
的 [Ignore]
属性,AutoMap
将正确设置它。
public class Project
{
public int { get; set; }
[Ignore]
public Owner? Owner { get; set; } = null;
}
或者,如果您需要使用 class 地图,则必须手动删除引用。
public class ProjectsClassMap : CsvHelper.Configuration.ClassMap<Project>
{
public ProjectsClassMap()
{
AutoMap(CultureInfo.CurrentCulture);
ReferenceMaps.Remove(ReferenceMaps.Find<Project>(m => m.Owner));
}
}