我有个实体
具有这些特性的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
中,我创建了这2的映射。
粗略地说
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类型的列表,并作为主题DTO的一部分返回OK。我试着使用这两种类型的联接并将其分配给query,但是它引发了映射配置没有正确配置的错误。
我该怎么做?
发布于 2021-06-30 21:19:54
为web接口定义DTO很好,但实现DTO的目的是提供特定于使用者需要的模型,并避免传递更多所需的数据或消费者无权查看的数据/架构信息。
假设TopicsMapped是一个包含某些字段的类,那么主题与TopicsMapped之间的关系是一对一的。通常,在一对一的关系中,您可能希望从相关实体中提供一些相关字段。映射DTO或ViewModels时要遵循的一般规则是不要将DTO(视图模型)与实体混合。(数据模型)这可能导致问题,因为如果TopicsMapped有对主题或其他实体/表的引用,那么在序列化DTO时,将该实体放入DTO中可能会看到延迟的加载调用或异常。或者在需要的地方为相关实体创建DTO图形,或者将DTO模型扁平化以表示您所关心的数据。
例如,如果TopicsMapped有一个名为"Name“的字段,我们希望包含在我们的web中,那么我们不需要整个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
}
然后使用automapper配置:
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“添加一个Automapper.QueryableExtensions子句。ProjectTo
和Map
的不同之处在于,对于Map
,在ToList
调用时会生成SQL。Map
将不得不懒散地从TopicMapping类加载数据,或者必须将其设置为急切地加载该数据。在这两种情况下,这实际上都包括来自TopicMapping的所有字段,即使在本例中我们只需要一个字段。另一方面,ProjectTo
允许Automapper在SQL生成中使用。结果的查询只会从主题和TopicMapping表返回DTO所需的字段,仅此而已。不需要急于加载相关实体,它会产生更精简的查询。
免责声明:据我所读,IQueryable
和Automapper的ProjectTo
应该支持Linq2SQL。如果遇到问题,我强烈建议考虑使用实体框架而不是Linq2SQL,因为它完全支持投影、急切和延迟加载。
https://stackoverflow.com/questions/68201263
复制相似问题