C# 实体框架核心:如何使用存储过程的结果集,并通过维护异步将其映射到对象和对象的对象

C# 实体框架核心:如何使用存储过程的结果集,并通过维护异步将其映射到对象和对象的对象,c#,sql,entity-framework,.net-core,entity-framework-core,C#,Sql,Entity Framework,.net Core,Entity Framework Core,我正在研究实体框架核心 我的任务是执行一个存储过程,并根据该存储过程的结果填充DTO。我很难用存储过程结果映射DTO类的属性,尤其是当我必须映射它的object(另一种类类型)属性时 考虑以下DTO类 public class Contact { public int Id { get; set; } public string Name { get; set; } public string EmailAddress { get; set; } public C

我正在研究实体框架核心

我的任务是执行一个存储过程,并根据该存储过程的结果填充DTO。我很难用存储过程结果映射DTO类的属性,尤其是当我必须映射它的object(另一种类类型)属性时

考虑以下DTO类

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string EmailAddress { get; set; }
    public Company Company { get; set; }
}

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
}
我对存储过程的SQL查询是:

SELECT
    Id                  = contact.id,
    Name                = LTRIM(RTRIM(contact.name)),
    EmailAddress        = LTRIM(RTRIM(contact.email)),
    -- company information
    CustomerId          = contact.cust_id
    CustomerName        = customer.name
FROM
    contact 
INNER JOIN
    customer ON contact.cust_id = customer.cust_id
我正在使用NuGet package
StoredProcedureEFCore
执行存储过程

以下是调用存储过程的代码:

Task<Contact> contactDetails = null;

_context.LoadStoredProc("usp_GetContactDetails")
        .Exec(r =>
        {
            contactDetails = r.FirstOrDefaultAsync<Contact>();
        });

// TODO: need to populate Company object
Task contactDetails=null;
_context.LoadStoredProc(“usp_GetContactDetails”)
.Exec(r=>
{
contactDetails=r.FirstOrDefaultAsync();
});
//TODO:需要填充公司对象
这段代码适用于Id、名称、电子邮件地址,但不适用于公司属性,因为我必须转到公司对象并填充该对象属性

根据我对
StoredProcedureEFCore
的研究,我们可以使用
ToDictionaryAsync
ToLookupAsync
来实现这一点,但我仍然无法做到


另外,还有一件事我必须异步完成。

首先,我认为不可能使用ToDictionaryAsync或ToLookupAsync映射StoredProcedureFore中的关系

但您可以创建自己的映射函数,如:

 public static async Task<Contact> MapContact(DbDataReader dataReader){
    if(await dataReader.ReadAsync() &&  dataReader.HasRows){
        Contact contact = new Contact();
        contact.Id =  dataReader.GetInt32( dataReader.GetOrdinal("Id"));
        contact.Name = dataReader.GetString(dataReader.GetOrdinal("Name"));
        contact.EmailAddress = dataReader.GetString(dataReader.GetOrdinal("EmailAddress"));
        Company company = new Company();
        company.Id = dataReader.GetInt32(dataReader.GetOrdinal("CompanyId"));
        company.Name = dataReader.GetString(dataReader.GetOrdinal("CompanyName"));
        contact.Company = company;
        return contact;
    }
    return null;
}
公共静态异步任务映射联系人(DbDataReader dataReader){ if(等待dataReader.ReadAsync()&&dataReader.HasRows){ 触点=新触点(); contact.Id=dataReader.GetInt32(dataReader.GetOrdinal(“Id”); contact.Name=dataReader.GetString(dataReader.GetOrdinal(“Name”); contact.EmailAddress=dataReader.GetString(dataReader.GetOrdinal(“EmailAddress”); 公司=新公司(); company.Id=dataReader.GetInt32(dataReader.GetOrdinal(“CompanyId”); company.Name=dataReader.GetString(dataReader.GetOrdinal(“CompanyName”); 联系人:公司=公司; 回接; } 返回null; } 并将其作为参数传递给Exec调用

Task<Contact> contactDetails = null;

_context.LoadStoredProc("usp_GetContactDetails")
    .Exec(r =>
    {
        contactDetails = MapContact(r)
    });
Task contactDetails=null;
_context.LoadStoredProc(“usp_GetContactDetails”)
.Exec(r=>
{
contactDetails=MapContact(r)
});

使用存储过程的原因是什么;为什么不直接在上下文中编写查询?另外,您的公司是模型中的一个嵌套属性,并且在结果中变平,您必须手动执行此操作
r.Select(x=>newcontact{..})
我必须使用存储过程。我不能使用LINQ或直接查询。你能使用“选择”吗?不,没有“选择”选项。这可以是一个选项,但不太通用。感谢您提供此解决方案!