如何使用automapper映射具有多个表的数据集

免责声明:这是一个旧的stackoverflowpost的副本粘贴,不再可用,但我有同样的问题,所以它似乎适合重新发布它,因为它从来没有回答。

我有一个存储过程将返回4个结果集(联系人,地址,电子邮件,电话),这些结果集填充到数据集中。 我想使用AutoMapper来填充复杂的对象。

public class Contact { public Guid ContactId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public List
Addresses { get; set; } public List Phones { get; set; } public List Emails { get; set; } } public partial class Address:BaseClass { public Guid ContactId { get; set; } public string Address1 { get; set; } public string Address2 { get; set; } public string Address3 { get; set; } public string City { get; set; } public string StateProvince { get; set; } public string PostalCode { get; set; } public string CountryCode { get; set; } } public class Email { public Guid EmailId { get; set; } public Guid ContactId { get; set; } public string EmailAddress { get; set; } } public class Phone { public Guid PhoneId { get; set; } public Guid ContactId { get; set; } public string Number { get; set; } public string Extension { get; set; } }

我有一个方法,将获取数据并返回联系人列表。 填充DataSet后,我定义表之间的关系。

我发现了许多使用CreateDataReader方法将DataSet(或表)转换为读者的示例,这就是我在这里所做的。 该方法实际上将第一个表解析为对象,但不会通过相关表进行枚举。

 public List GetContacts() { List theList = null; // Get the data Database _db = DatabaseFactory.CreateDatabase(); DataSet ds = db.ExecuteDataSet(CommandType.StoredProcedure, "GetContacts"); //The dataset should contain 4 tables if (ds.Tables.Count == 4) { //Create the maps Mapper.CreateMap(); // I think I'm missing something here Mapper.CreateMap(); Mapper.CreateMap(); Mapper.CreateMap(); //Define the relationships ds.Relations.Add("ContactAddresses", ds.Tables[0].Columns["ContactId"], ds.Tables[1].Columns["ContactId"]); ds.Relations.Add("ContactEmails", ds.Tables[0].Columns["ContactId"], ds.Tables[2].Columns["ContactId"]); ds.Relations.Add("ContactPhones", ds.Tables[0].Columns["ContactId"], ds.Tables[3].Columns["ContactId"]); IDataReader dr = ds.CreateDataReader(); theList = Mapper.Map<List>(dr); } return (theList); } 

我觉得好像我在Contact对象的映射中遗漏了一些东西,但我找不到一个好的例子可以遵循。

如果我手动填充联系人对象然后传递给我的控制器,它将使用直接映射正确加载ContactModel对象

 public ActionResult Index() { //From the ContactController Mapper.CreateMap(); Mapper.CreateMap
(); List theList = Mapper.Map<List, List>(contacts); return View(theList); }

我想做甚么可能吗?

IDataReader映射器非常简单,它可以从数据读取器中填充对象,它可以按列名映射对象属性。 它不是为了创建一个带有关系等的复杂数据结构而设计的。

此外,DataSet.CreateDataReader将生成一个多结果集数据读取器 – 即读者将为每个表都有很少的结果集,但它不会保留关系。

因此,为了得到你想要的东西,你需要为每个表创建阅读器,将每个阅读器映射到不同的集合,然后使用这些结果来创建最终的复杂对象。

在这里,我提供了简单的方法,但你可以疯狂,并创建自定义解析器等,以封装一切。

 using System; using System.Collections.Generic; using System.Data; using System.Linq; using AutoMapper; using NUnit.Framework; namespace StackOverflowExample.Automapper { public class Contact { public Guid ContactId { get; set; } public string Name { get; set; } public List
Addresses { get; set; } } public partial class Address { public Guid AddressId { get; set; } public Guid ContactId { get; set; } public string StreetAddress { get; set; } } [TestFixture] public class DatasetRelations { [Test] public void RelationMappingTest() { //arrange var firstContactGuid = Guid.NewGuid(); var secondContactGuid = Guid.NewGuid(); var addressTable = new DataTable("Addresses"); addressTable.Columns.Add("AddressId"); addressTable.Columns.Add("ContactId"); addressTable.Columns.Add("StreetAddress"); addressTable.Rows.Add(Guid.NewGuid(), firstContactGuid, "c1 a1"); addressTable.Rows.Add(Guid.NewGuid(), firstContactGuid, "c1 a2"); addressTable.Rows.Add(Guid.NewGuid(), secondContactGuid, "c2 a1"); var contactTable = new DataTable("Contacts"); contactTable.Columns.Add("ContactId"); contactTable.Columns.Add("Name"); contactTable.Rows.Add(firstContactGuid, "contact1"); contactTable.Rows.Add(secondContactGuid, "contact2"); var dataSet = new DataSet(); dataSet.Tables.Add(contactTable); dataSet.Tables.Add(addressTable); Mapper.CreateMap(); Mapper.CreateMap().ForMember(c=>c.Addresses, opt=>opt.Ignore()); //act var addresses = GetDataFromDataTable
(dataSet, "Addresses"); var contacts = GetDataFromDataTable(dataSet, "Contacts"); foreach (var contact in contacts) { contact.Addresses = addresses.Where(a => a.ContactId == contact.ContactId).ToList(); } } private IList GetDataFromDataTable(DataSet dataSet, string tableName) { var table = dataSet.Tables[tableName]; using (var reader = dataSet.CreateDataReader(table)) { return Mapper.Map>(reader).ToList(); } } } }

我参加派对的时间非常晚,但万一这会帮助别人。

我所做的是使用Json.NET将我的数据集序列化为JSON字符串。

 var datasetSerialized = JsonConvert.SerializeObject(dataset, Formatting.Indented); 

在Visual Studio中调试时将json视为字符串,并将其复制到剪贴板。

然后在Visual Studio中转到编辑 – >选择性粘贴 – >将JSON粘贴为类

然后,您将为每个具有关系的表格提供POCO。

最后,将JSON反序列化为粘贴JSON As Classes时创建的“RootObject”。

 var rootObj = JsonConvert.DeserializeObject(datasetSerialized);