我有一个旧的旧数据库,该数据库已转换为CSV,我试图在其中使用CSVHelper
解析和分解数据,以便播种新数据库(使用实体框架)。
例如,我有以下CSV标头;
Rec,ID,FirstName,Lastname,Email,BusinessPhone,Company,JobTitle,HomePhone,MobilePhone,FaxNumber,Address,City,State,PostalCode,Country,WebPage,Term,Website,CompanyReg,YearEstablished,AgreementNumber,ExpiryDate
(为简洁起见,这是一种减少)
在新系统下,我们具有以下POCO地图(为简便起见,再次简化;]
public class Company
{
public string Name { get; set; }
public string Website { get; set; }
public int AddressId { get; set; }
public Address Address { get; set; }
public IList<Contact> Contacts { get; set; }
}
public class Address
{
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string Town { get; set; }
public string Region { get; set; }
public string PostCode { get; set; }
public string Country { get; set; }
public bool IsPrimaryAddress { get; set; }
}
public class Contact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string HomeTelephone { get; set; }
public string BusinessTelephone { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
public string Notes { get; set; }
public bool IsPrimaryContact { get; set; }
}
我的映射器如下;
public sealed class CompanyMap : ClassMap<Company>
{
public CompanyMap()
{
Map(m => m.Id).Name("ID");
Map(m => m.Name).Name("Company");
Map(m => m.Website).Name("WebPage");
References<CompanyAddressFromCompanyMap>(m => m.Address);
References<PrimaryContactFromCompanyMap>(m => m.Contacts);
}
}
public sealed class CompanyAddressFromCompanyMap: ClassMap<Address>
{
public CompanyAddressFromCompanyMap()
{
Map(m => m.Address1).Name("Address");
Map(m => m.Town).Name("City");
Map(m => m.Region).Name("State");
Map(m => m.PostCode).Name("PostalCode");
Map(m => m.Country).Name("Country");
Map(m => m.IsPrimaryAddress).Default(true);
}
}
public sealed class PrimaryContactFromCompanyMap : ClassMap<Contact>
{
public PrimaryContactFromCompanyMap()
{
Map(m => m.FirstName).Name("FirstName");
Map(m => m.LastName).Name("LastName");
Map(m => m.HomeTelephone).Name("HomePhone");
Map(m => m.BusinessTelephone).Name("BusinessPhone");
Map(m => m.Mobile).Name("MobilePhone");
Map(m => m.Email).Name("Email");
Map(m => m.IsPrimaryContact).Default(true);
}
}
但是这会引发错误;
System.ArgumentException: Property 'System.String FirstName' is not defined for type 'System.Collections.Generic.IList
1 [Contact]'(参数'property')`
我认为这可能是因为这是一个IList<Contact>
?
任何人都可以就错误提出建议,以及如何映射到嵌套集合?
这个问题很有趣。为了简化起见,我删除了某些csv字段。我刚刚在配置中注册了您的ClassMap,并使用了一个简单的Map(m => m.Contacts).ConvertUsing(...)。
我无法弄清楚如何使用TypeConverter,但这可能也可行。
可能最好是避免使用References
这是完整的xunit测试示例。
public class CsvHelper
{
internal string csv = @"
Company,Address,FirstName,AnotherName
MyCompany,MyAddress,MyFirstName,MyAnotherName
";
public CsvHelper()
{
}
[Fact]
public void Stackoverflow()
{
using var r = new StringReader(csv);
var conf = new CsvConfiguration(CultureInfo.InvariantCulture);
conf.Delimiter = ",";
conf.RegisterClassMap<CompanyMap>();
conf.RegisterClassMap<PrimaryContactFromCompanyMap>();
using var cr = new CsvReader(r, conf);
var records = cr.GetRecords<Company>().ToList();
Assert.True(records.Count == 1);
}
}
public class Company
{
public string CompanyName { get; set; }
public Address Address { get; set; }
public IList<Contact> Contacts { get; set; }
}
public class Address
{
public string Address1 { get; set; }
}
public class Contact
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public sealed class CompanyMap : ClassMap<Company>
{
public CompanyMap()
{
Map(m => m.CompanyName).Name("Company");
References<CompanyAddressFromCompanyMap>(m => m.Address);
Map(m => m.Contacts).ConvertUsing(r =>
{
var c = r.GetRecord<Contact>();
return new List<Contact>() { c };
});
}
}
public sealed class CompanyAddressFromCompanyMap : ClassMap<Address>
{
public CompanyAddressFromCompanyMap()
{
Map(m => m.Address1).Name("Address");
}
}
public sealed class PrimaryContactFromCompanyMap : ClassMap<Contact>
{
public PrimaryContactFromCompanyMap()
{
Map(m => m.FirstName).Name("FirstName");
Map(m => m.LastName).Name("AnotherName");
}
}
}