如何使用automapper映射与多个表的数据集 [英] How do I use automapper to map a dataset with multiple tables

查看:2959
本文介绍了如何使用automapper映射与多个表的数据集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

免责声明:这是从旧的计算器职位,不再提供一个复制粘贴,但我有exaclty同样的问题,所以它似乎应当重新发布它,因为它从来没有回答

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

I have a stored procedure that will return 4 result sets (contacts, addresses, email, phones) which is populated into a dataset. I would like to use AutoMapper to populate a complex object.

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是填充,我定义的表之间的关系。

I have a method that will get data and return a list of contact. After the DataSet is populate, I define the relationships between the tables.

我发现,你的数据集(或表)转换为读者很多例子使用CreateDataReader方法这就是我在这里做什么。该方法实际上将解析第一个表到对象,但不会通过相关的表列举

I found many examples where you convert the DataSet (or table) to a reader using the CreateDataReader method and that is what I'm doing here. The method will in fact parse the first table into the object, but will not enumerate through the related tables.

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);    
}



我觉得好像我错过在映射的东西联系对象,但我不能找到一个很好的榜样。

I feel as though I'm missing something in the mapping for the Contact object, but I just can't find a good example to follow.

如果我手动填充接触对象,然后传递是我的控制器,它会正常加载ContactModel使用直接映射对象

If I manually populate the contact object and then pass is to my controller, it will properly load the ContactModel object using a direct mapping

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);
}



是我想要做甚至可能吗?

Is what I want to do even possible?

推荐答案

IDataReader的映射是非常简单的,它可以填充对象了数据读取器,它由列名对象属性映射的。它不是为了创建关系等复杂的数据结构

IDataReader mapper is very simple one, it can populate an object out of a data reader, where it maps the object properties by column names. It was not designed to create a complex data structures with relations, etc.

此外,DataSet.CreateDataReader会产生多个ResultSet数据读取器 - 即读者将有几结果集为每个表,但不会保持关系。

Also, the DataSet.CreateDataReader will produce a multiple resultset data reader - i.e. the reader will have few result sets for each table, but it will not preserve the relations.

因此,为了得到你想要什么,你需要为每个表中创建阅读器,地图中的每个读者不同的集合,然后使用这些结果来创建最终的复杂对象(S)。

So, in order to get what you want, you need to create reader for each table, map each reader to different collection, and then use these results to create the final complex object(s).

下面我提供简单的方法,但你可以去野外,和创建自定义的解析器的,等等,封装一切。

Here I'm providing the simplistic approach, but you can go wild, and create custom resolvers, etc., to encapsulate everything.

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();
            }
        }
    }
} 

这篇关于如何使用automapper映射与多个表的数据集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆