簡體   English   中英

如何使用automapper映射具有多個表的數據集

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM