C# 存储过程返回复杂类型,我使用AutoMapper将其映射到模型,但未设置外键对象

C# 存储过程返回复杂类型,我使用AutoMapper将其映射到模型,但未设置外键对象,c#,entity-framework,asp.net-mvc-5,entity-framework-6,automapper,C#,Entity Framework,Asp.net Mvc 5,Entity Framework 6,Automapper,我使用AutoMapper将数据层(EF6 DbFirst AutoGenerated layer)映射到模型层(Pocos/Dtos)。我感到困惑的一点是,当使用存储过程时,它们会返回一个复杂的对象,例如Customer\u GetCustomers\u Result,因此我必须使用AutoMapper将其映射到我的CustomerPoco,并且我会丢失外键对象属性,例如Customer.Address,因为它们不在我的复杂类型中 以下是我的CustomerPoco的一个示例: public

我使用AutoMapper将数据层(EF6 DbFirst AutoGenerated layer)映射到模型层(Pocos/Dtos)。我感到困惑的一点是,当使用存储过程时,它们会返回一个复杂的对象,例如Customer\u GetCustomers\u Result,因此我必须使用AutoMapper将其映射到我的CustomerPoco,并且我会丢失外键对象属性,例如Customer.Address,因为它们不在我的复杂类型中

以下是我的CustomerPoco的一个示例:

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Phone { get; set; }
    public string Fax { get; set; }
    public string Website { get; set; }
    public int AddressId { get; set; }

    // THESE END UP NOT GETTING SET
    public List<CustomerContact> Contacts { get; set; }
    public Address Address { get; set; }
}
公共类客户
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公用字符串电话{get;set;}
公共字符串传真{get;set;}
公共字符串网站{get;set;}
public int AddressId{get;set;}
//这些最终没有得到设置
公共列表联系人{get;set;}
公共广播地址{get;set;}
}
在我的GetCustomers存储过程中,让我们假设我做了一些简单的事情,比如:从CUSTOMER中选择*。它返回一个复杂的对象context.Customer\u GetCustomers\u结果。然后我必须将这个复杂的对象映射到我的CustomerPoco。联系人和地址未设置。我该怎么做

以下是我的客户映射:

    CreateMap<Customer, Model.Customer>()
        .ForMember(dest => dest.Contacts, opt => opt.MapFrom(src => src.CustomerContacts));

    CreateMap<Customer_GetCustomers_Result, Model.Customer>();
CreateMap()
.ForMember(dest=>dest.Contacts,opt=>opt.MapFrom(src=>src.CustomerContacts));
CreateMap();

这实际上可能是个糟糕的问题。我相信如果我真的想使用存储过程来返回我的列表,我将需要进行连接,并实际返回select中Address的属性,例如。。。a、 Address1、a.Address2等。那么有没有办法将它们映射到Model.Customer.Address,即使它们都被拆分为单独的属性?

我想您在这里有两个单独的问题需要解决。第一个是如何让存储过程返回所有数据并将其绑定到EF复杂类型中。这里有几篇文章,应该会有所帮助。本质上,编写存储过程以返回多个结果集,编写几行代码以前进到下一个结果集并将其读入上下文


要从AutoMapper获得所需的映射,还需要为用作属性的每种类型添加映射(例如,从EF“Address”类型到POCO“Address”类型的映射)。

这实际上相当简单,但可能需要设置一些AutoMapper配置。存储过程实际上只能返回平坦的结果,但仍然可以传递所有关系的所有字段。如果您想几乎不需要配置,那么实际上只需要让存储过程以扁平格式返回属性名。例如,
AddressCity
而不是像
City
这样的东西。如果要从中映射的对象具有类似于
AddressCity
的属性,并且要映射到的对象具有导航属性
Address
,该属性本身具有属性
City
,则AutoMapper将自动适当地填写该属性。如果不想或无法更改存储过程返回的列名,则只需配置AutoMapper:

AutoMapper.Mapper.CreateMap<Customer_GetCustomers_Result, Custom>()
    .ForMember(dest => dest.Address, opts => opts.MapFrom(src => new Address
    {
        City = src.City,
        // etc.
    });
AutoMapper.Mapper.CreateMap()
.ForMember(dest=>dest.Address,opts=>opts.MapFrom(src=>newaddress
{
城市=src.城市,
//等等。
});
如果您有更复杂的场景,如可枚举导航属性,则此方法不会真正起作用。在这种情况下,您最好分多个步骤执行此操作,例如使用一个存储过程来检索主对象以及可以与其展开的所有对象。这样,您就可以映射到所需的类型。然后,使用单独的存储过程基于主对象的id或其他内容查找可枚举项,并将这些项映射到以前映射的对象上的可枚举属性的过程。

public IEnumerable sample()
{
使用(SqlConnection con=newsqlconnection(connStr))
{
DataTable dt=新的DataTable();
SqlCommand cmd=newsqlcommand(“proedurename”,con);
cmd.CommandType=CommandType.storedProcess;
if(cmd.Connection.State!=ConnectionState.Open)
cmd.Connection.Open();
var retObject=新列表();
使用(var dataReader=cmd.ExecuteReader())
{
while(dataReader.Read())
{
var dataRow=new ExpandoObject()作为IDictionary;
对于(变量iFiled=0;iFiled
您可以显示您设置的映射吗?好的,我添加了它们。我添加联系人FormMember的原因是因为我在模型中将名称从CustomerContacts更改为Contacts。我是否必须向映射中添加一些内容以确保Address对象被绑定?我注意到自动生成的类Customer\u GetCustomers\u Resultt中没有像Data.Customer和my Model.Customer类那样的Address对象属性。这是有意义的,因为程序最多返回AddressId。有没有办法解决这个问题?这正是我需要知道的。我在查看AutoMapper文档时看到,如果对象中有对象,它将能够只要命名正确,就映射它。我应该考虑使用正确的名称从Get-stored过程返回我的列。非常感谢!