如何解决在返回使用自动映射器映射的 DTO 时,如何为其分配子类类型的列表?
我有一个实体
Topics
具有这些属性
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
并且它有属性
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
中,我创建了这两个的映射。
大致,
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Topics,TopicsDTO>();
});
现在在 webapi 方法中,我正在使用 linq to sql
并且我写了这样的东西
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 类型列表,并作为 TOPICs DTO 的一部分返回 OK。我尝试采用两种类型的连接并分配给查询,但它抛出了映射配置未正确配置的错误。
我该怎么做?
解决方法
为您的 Web 界面定义 DTO 是好的,但实现 DTO 的目的是提供一个特定于消费者需求的模型,并避免传递更多需要的数据,或消费者拥有的数据/模式信息无权查看。
假设TopicsMapped是一个包含一些字段的类,Topic和TopicsMapped之间是一对一的关系。通常在一对一关系中,您可能希望提供来自相关实体的一些相关字段。映射 DTO 或 ViewModel 时要遵循的一般规则是不要将 DTO(视图模型)与实体混合。 (数据模型)这可能会导致问题,因为如果 TopicsMapped 引用回 Topic 或其他实体/表,则将该实体放入 DTO 中可能会在序列化 DTO 时看到延迟加载调用或异常。在需要时为相关实体创建 DTO 图,或将 DTO 模型展平以表示您关心的数据。
例如,如果 TopicsMapped 有一个名为“Name”的字段,我们希望将其包含在我们的 Web API 中,我们不需要整个 TopicsMapped 模型,只需要该字段。所以我们可以在 DTO 中将其压平:
[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
}
然后使用自动映射器配置:
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
:
var topicDTOs = Context.Topics
.ProjectTo<TopicDTO>(config)
.ToList();
这将涉及为“Automapper.QueryableExtensions”添加一个 using
子句。 ProjectTo
和 Map
之间的区别在于,对于 Map
,SQL 生成发生在您的 ToList
调用中。 Map
将不得不求助于从 TopicMapping 类延迟加载数据,或者您必须将其设置为预先加载该数据。在这两种情况下,这基本上包括来自 TopicMapping 的 所有 字段,即使在此示例中我们只需要 1 个字段。 ProjectTo
另一方面让 Automapper 参与 SQL 生成。结果查询只会从 Topic 和 TopicMapping 表中返回 DTO 需要的字段,仅此而已。无需急切加载相关实体,它会生成更加精简的查询。
免责声明:据我所知,Linq2SQL 应该支持 IQueryable
和 Automapper 的 ProjectTo
。如果您遇到问题,我强烈建议您考虑使用 Entity Framework 而不是 Linq2SQL,因为它完全支持投影、预先加载和延迟加载。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。