我正在尝试将 CSV 文件中的测试数据加载到可以加载到内存中 EF Core DB 上下文中的记录中。
我有一个简化的实体,如下所示:
public class Project
{
public int { get; set; }
public Owner? Owner { get; set; } = null;
}
Run Code Online (Sandbox Code Playgroud)
A类图:
public class ProjectsClassMap : CsvHelper.Configuration.ClassMap<Projects>
{
public ProjectsClassMap()
{
AutoMap(CultureInfo.CurrentCulture);
Map(m => m.Owner).Ignore();
}
}
Run Code Online (Sandbox Code Playgroud)
然后是一个加载数据的函数,如下所示:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
问题在于 Owner 设置为新值而不是默认值 null,这会在尝试保存到 DbContext 时导致验证错误。如何将复杂引用类型保留为 null 而不是 new?
尝试这个
public class ProjectsClassMap : CsvHelper.Configuration.ClassMap<Project>
{
public ProjectsClassMap()
{
var config = new CsvConfiguration(CultureInfo.CurrentCulture)
{
IgnoreReferences = true
};
AutoMap(config);
}
}
Run Code Online (Sandbox Code Playgroud)
来自@JoshClose 的更新
这里的问题是 AutoMap 将设置树中的所有属性,并且忽略该属性不会删除 Owner 上的所有属性。
使用不带和[Ignore]的属性将正确设置它。ProjectsClassMapAutoMap
public class Project
{
public int { get; set; }
[Ignore]
public Owner? Owner { get; set; } = null;
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您需要使用类映射,则必须手动删除引用。
public class ProjectsClassMap : CsvHelper.Configuration.ClassMap<Project>
{
public ProjectsClassMap()
{
AutoMap(CultureInfo.CurrentCulture);
ReferenceMaps.Remove(ReferenceMaps.Find<Project>(m => m.Owner));
}
}
Run Code Online (Sandbox Code Playgroud)