You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何将存储过程返回的数据填充到Person类的内部PhoneNumber对象

解决方案

你可以选择以下两种方案实现映射,根据你使用的EF Core版本选择即可:

方案1:中间DTO承接映射(兼容所有EF Core版本,最稳妥)

先定义和存储过程返回字段完全匹配的无键DTO承接查询结果,再手动映射到Person实体。

1.1 定义基础实体

public class PhoneNumber
{
    public string AreaCode { get; set; }
    public string Phone { get; set; }
    public string Extension { get; set; }
}

public class Person
{
    // 个人基础信息示例
    public int Id { get; set; }
    public string Name { get; set; }
    // 地址信息示例
    public string Address { get; set; }
    // 电话属性
    public PhoneNumber BusinessPhone { get; set; }
    public PhoneNumber ResidencePhone { get; set; }
}

1.2 定义存储过程承接DTO

public class PersonSpDTO
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    // 商务电话字段和存储过程返回完全匹配
    public string BusinessAreaCode { get; set; }
    public string BusinessPhone { get; set; }
    public string BusinessExtension { get; set; }
    // 住宅电话字段和存储过程返回完全匹配
    public string ResidentialAreaCode { get; set; }
    public string ResidentialPhone { get; set; }
    public string ResidentialExtension { get; set; }
}

1.3 配置DbContext

在DbContext的OnModelCreating方法中配置DTO为无键实体:

modelBuilder.Entity<PersonSpDTO>().HasNoKey();

1.4 查询并映射

var people = context.Set<PersonSpDTO>()
    .FromSqlRaw("EXEC GetPersonDetails")
    .AsEnumerable()
    .Select(dto => new Person
    {
        Id = dto.Id,
        Name = dto.Name,
        Address = dto.Address,
        BusinessPhone = new PhoneNumber
        {
            AreaCode = dto.BusinessAreaCode,
            Phone = dto.BusinessPhone,
            Extension = dto.BusinessExtension
        },
        ResidencePhone = new PhoneNumber
        {
            AreaCode = dto.ResidentialAreaCode,
            Phone = dto.ResidentialPhone,
            Extension = dto.ResidentialExtension
        }
    })
    .ToList();

方案2:构造函数映射(仅支持EF Core 8及以上版本,代码更简洁)

直接在Person实体中定义匹配存储过程返回字段的构造函数,在构造函数内部完成PhoneNumber对象的初始化,不需要中间DTO。

2.1 改造Person实体增加构造函数

public class Person
{
    // 构造函数参数名和存储过程返回字段名完全匹配(不区分大小写)
    public Person(int id, string name, string address, 
        string businessAreaCode, string businessPhone, string businessExtension,
        string residentialAreaCode, string residentialPhone, string residentialExtension)
    {
        Id = id;
        Name = name;
        Address = address;
        BusinessPhone = new PhoneNumber
        {
            AreaCode = businessAreaCode,
            Phone = businessPhone,
            Extension = businessExtension
        };
        ResidencePhone = new PhoneNumber
        {
            AreaCode = residentialAreaCode,
            Phone = residentialPhone,
            Extension = residentialExtension
        };
    }

    // 原有属性保持不变
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public PhoneNumber BusinessPhone { get; set; }
    public PhoneNumber ResidencePhone { get; set; }
}

2.2 直接查询

var people = context.Set<Person>()
    .FromSqlRaw("EXEC GetPersonDetails")
    .ToList();
注意事项
  • 存储过程返回的字段名需要和接收的DTO属性/构造参数名完全匹配,EF Core映射时不区分大小写
  • 若返回字段可能为null,建议将PhoneNumber的属性设置为可空类型,避免空引用异常
  • 使用无键DTO的方案兼容所有EF Core版本,适用范围更广;构造函数映射方案仅支持EF Core 8及以上版本,代码更简洁

内容的提问来源于stack exchange,提问作者CrazyCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 20:36:00