[英]How do I use automapper to map a dataset with multiple tables
免責聲明:這是一個舊的stackoverflow帖子的副本粘貼,不再可用,但我有同樣的問題,所以它似乎適合重新發布它,因為它從來沒有回答。
我有一個存儲過程將返回4個結果集(聯系人,地址,電子郵件,電話),這些結果集填充到數據集中。 我想使用AutoMapper來填充復雜的對象。
public class Contact
{
public Guid ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Address> Addresses { get; set; }
public List<Phone> Phones { get; set; }
public List<Email> 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<Contact> GetContacts()
{
List<Contact> 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<IDataReader, Contact>(); // I think I'm missing something here
Mapper.CreateMap<IDataReader, Address>();
Mapper.CreateMap<IDataReader, Email>();
Mapper.CreateMap<IDataReader, Phone>();
//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<Contact>>(dr);
}
return (theList);
}
我覺得好像我在Contact對象的映射中遺漏了一些東西,但我找不到一個好的例子可以遵循。
如果我手動填充聯系人對象然后傳遞給我的控制器,它將使用直接映射正確加載ContactModel對象
public ActionResult Index()
{
//From the ContactController
Mapper.CreateMap<Contact, Models.ContactModel>();
Mapper.CreateMap<Address, Models.AddressModel>();
List<Models.ContactModel> theList = Mapper.Map<List<Contact>, List<Models.ContactModel>>(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<Address> 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<IDataReader, Address>();
Mapper.CreateMap<IDataReader, Contact>().ForMember(c=>c.Addresses, opt=>opt.Ignore());
//act
var addresses = GetDataFromDataTable<Address>(dataSet, "Addresses");
var contacts = GetDataFromDataTable<Contact>(dataSet, "Contacts");
foreach (var contact in contacts)
{
contact.Addresses = addresses.Where(a => a.ContactId == contact.ContactId).ToList();
}
}
private IList<T> GetDataFromDataTable<T>(DataSet dataSet, string tableName)
{
var table = dataSet.Tables[tableName];
using (var reader = dataSet.CreateDataReader(table))
{
return Mapper.Map<IList<T>>(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<RootObject>(datasetSerialized);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.