首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当返回使用automapper映射的DTO时,如何分配它的子类类型列表?

当返回使用automapper映射的DTO时,如何分配它的子类类型列表?
EN

Stack Overflow用户
提问于 2021-06-30 20:29:00
回答 1查看 918关注 0票数 0

我有个实体

具有这些特性的Topics

代码语言:javascript
运行
复制
1. public string Name {get; set;}
2. public string Location {get; set;}
3. public string Identity {get; set;}
4. public TopicsMapped TopicsMapped {get; set;}

另外,我有一个DTO,即TopicsDTO,它具有属性

代码语言:javascript
运行
复制
1. public string Name {get; set;}
2. public string Location {get; set;}
3. public string Identity {get; set;}
4. public TopicsMapped TopicsMapped {get; set;}

因此,在Automapper.config中,我创建了这2的映射。

粗略地说

代码语言:javascript
运行
复制
    var config = new MapperConfiguration(cfg => {
    cfg.CreateMap<Topics, TopicsDTO>();
    
});

现在,在webapi方法中,我使用了linq to sql,我编写了这样的东西

代码语言:javascript
运行
复制
 var query= (from t in topics select t).tolist();

 Topics t= new topics();

 var mapper = new Mapper(config);
 var topicsDTO = mapper.Map<List<TopicsDTO>>(query);
 
 return OK(topicsDTO)  //since the webapi method returning IHttpActionResult.

但我的问题是,我必须分配一个TopicsMapped类型的列表,并作为主题DTO的一部分返回OK。我试着使用这两种类型的联接并将其分配给query,但是它引发了映射配置没有正确配置的错误。

我该怎么做?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-30 21:19:54

为web接口定义DTO很好,但实现DTO的目的是提供特定于使用者需要的模型,并避免传递更多所需的数据或消费者无权查看的数据/架构信息。

假设TopicsMapped是一个包含某些字段的类,那么主题与TopicsMapped之间的关系是一对一的。通常,在一对一的关系中,您可能希望从相关实体中提供一些相关字段。映射DTO或ViewModels时要遵循的一般规则是不要将DTO(视图模型)与实体混合。(数据模型)这可能导致问题,因为如果TopicsMapped有对主题或其他实体/表的引用,那么在序列化DTO时,将该实体放入DTO中可能会看到延迟的加载调用或异常。或者在需要的地方为相关实体创建DTO图形,或者将DTO模型扁平化以表示您所关心的数据。

例如,如果TopicsMapped有一个名为"Name“的字段,我们希望包含在我们的web中,那么我们不需要整个TopicsMapped模型,只需要这个字段。所以我们可以在DTO中把它压平:

代码语言:javascript
运行
复制
[Serializable]
public class TopicDTO
{
    public int TopicId { get; set; }
    public string Name { get; set; }
    public string Location { get; set; }
    public string Identity { get; set; }
    public string MappedName { get; set; } // <- Will map to TopicsMapped.Name
}

然后使用automapper配置:

代码语言:javascript
运行
复制
var config = new MapperConfiguration(cfg => 
{
    cfg.CreateMap<Topics, TopicsDTO>()
        .ForMember(x => x.MappedName, opt => opt.MapFrom(src => src.TopicsMapped.Name));
};

默认情况下,Automapper可以使用约定从源对象中为目标字段计算映射,如果您遵循DTO中的这些约定,就有可能避免显式映射,但是如果更改属性名称,我更愿意使用显式映射来避免猜测和错误。它还有助于确保正确计算属性的使用数量。Linq2SQL应该提供对IQueryable的访问,因此要正确利用投影/w Automapper,您需要使用ProjectTo而不是Map

代码语言:javascript
运行
复制
var topicDTOs = Context.Topics
    .ProjectTo<TopicDTO>(config)
    .ToList();

这将涉及为"Automapper.QueryableExtensions“添加一个Automapper.QueryableExtensions子句。ProjectToMap的不同之处在于,对于Map,在ToList调用时会生成SQL。Map将不得不懒散地从TopicMapping类加载数据,或者必须将其设置为急切地加载该数据。在这两种情况下,这实际上都包括来自TopicMapping的所有字段,即使在本例中我们只需要一个字段。另一方面,ProjectTo允许Automapper在SQL生成中使用。结果的查询只会从主题和TopicMapping表返回DTO所需的字段,仅此而已。不需要急于加载相关实体,它会产生更精简的查询。

免责声明:据我所读,IQueryable和Automapper的ProjectTo应该支持Linq2SQL。如果遇到问题,我强烈建议考虑使用实体框架而不是Linq2SQL,因为它完全支持投影、急切和延迟加载。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68201263

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档