我已将存储过程附加到数据库,该数据库应仅通过简单搜索即可返回结果。该查询已添加到我的实体并调用常规方法。我面临的问题是将此过程的结果作为列表存储到特定的DTO。
是否有任何方法可以有效地将此存储过程的结果作为列表存储到DTO?
以下是我到目前为止所拥有的
Controller:
[Produces("application/json")]
[RoutePrefix("api/jobs")]
public class OutputController : ApiController
{
private TestCoastalToolsEntities _output;
public OutputController()
{
_output = new TestCoastalToolsEntities();
_output.Configuration.ProxyCreationEnabled = false;
}
/**Search**/
// POST: api/postsearch
[System.Web.Http.HttpPost, System.Web.Http.Route("postsearch")]
public async Task<IHttpActionResult> PostSearch(SearchInputDTO srequest)
{
OutputDTO<SearchInputDTO> output = new OutputDTO<SearchInputDTO>();
SearchInputDTO SearchInput = null;
var searchString = srequest.SearchValue.ToString();
SearchInput.Results = _output.searchLog2(searchString);
if (_oput != null)
{
output.Success = true;
output.Results = _SearchInput.Results;
var json = new JavaScriptSerializer().Serialize(output);
return Ok(json);
}
return Ok(_ot);
}
}
}
-------------------------------------
Search DTO:
namespace toolPortal.API.Data.DTO
{
public class SearchInputDTO
{
public List<object> Results { get; set; }
public SearchInputDTO(output output) {
this.ID = output.ID;
this.Name = output.Name;
this.Job = output.Job;
this.Start = output.Start;
this.End = output.End;
this.Logs = output.Logs;
}
}
}
预期结果是存储过程运行并将结果列表存储到SearchInputResults。从那里,这些结果应该存储在另一个DTO中,以便在返回时传递出去。
答案 0 :(得分:0)
使用EF,您将需要利用Select()
将实体映射到DTO,尽管您将需要考虑DTO的整个结构。例如,“日志”数据结构将包括什么?是单个字符串值,字符串列表还是日志记录列表?
使用Select()
需要利用属性设置器,而不是接受实体的构造函数。
这样的模式:
public class Entity
{
public string Field { get; set; }
}
public class Dto
{
public string Field { get; set; }
}
var dtos = context.Entities
.Where(x => x.IsActive)
.Select(x => new Dto
{
Field = x.Field
})
.ToList();
使用构造函数查看示例: 公开课Dto { 公共字符串字段{get;私人套装; }
public Dto(Entity entity)
{
Field = entity.Field;
}
}
var dtos = context.Entities
.Where(x => x.IsActive)
.Select(x => new Dto(x))
.ToList();
这不适用于EF&Select。 EF可以映射到对象,但只能通过属性和无参数的构造函数。有一个需要注意的技巧,但是请避免看到它:
var dtos = context.Entities
.Where(x => x.IsActive)
.ToList()
.Select(x => new Dto(x))
.ToList();
在选择之前加上额外的ToList()
,该调用将起作用,因为EF将执行查询并返回实体列表,然后将Select()
作为Linq2Object查询执行。之所以要避免这种情况,是因为EF将从实体中选择 all 属性,在该属性中,我们仅应撤回我们关心的属性。如果您的Dto构造函数填充开始在相关实体上进行迭代,也很容易陷入延迟加载性能陷阱。使用Select
可以从实体和任何相关实体仅加载您需要的字段,从而使EF可以针对所需数据构建有效的查询,而无需任何延迟加载陷阱。
使用AutoMapper,可以通过设置从实体到DTO的映射,然后利用ProjectTo<Dto>()
来简化此过程。
因此,如果您希望DTO用成功的结果集合来表示结果(例如成功标志,错误消息):
[Serializable]
// Our results container.
public class SearchResultsDTO
{
public bool IsSuccessful { get; private set; } = false;
public string ErrorMessage { get; private set; }
public ICollection<SearchResultDTO> Results { get; private set; } = new List<SearchResultDTO>();
private SearchResultsDTO() {}
public static SearchResultsDTO Success(ICollection<SearchResultDTO> results)
{
var results = new SearchResultsDTO
{
IsSuccessful = true,
Results = results
};
return results;
}
public static SearchResultsDTO Failure(string errorMessage)
{
var results = new SearchResultsDTO
{
ErrorMessage = errorMessage
};
return results;
}
}
[Serializable]
public class SearchResultDTO
{
public int ID {get; set;}
public string Name {get; set;}
public string Job {get; set;}
public DateTime Start {get; set;}
public DateTime End {get; set;}
public ICollection<string> Logs {get; set;} = new List<string>();
}
然后从DbContext中填充这些内容:(在存储库中或任何读取数据的地方)
using (var context = new SearchContext())
{
var results = context.Logs
.Where(x => x.Name.Contains(sRequest))
.Select(x => new SearchResultDTO
{
ID = x.ID,
Name = x.Name,
Job = x.Job,
Start = x.Start,
End = x.End,
Logs = x.LogLines.Select(y => y.Line).ToList(),
}).ToList();
var resultDto = SearchResultsDTO.Success(results);
return resultsDto;
}
这假定日志条目具有作业,名称,开始,结束日期/时间,然后是“行”列表或要显示为“日志”的条目。 (其中,日志表具有相关的LogLine表,例如具有一行或多行)。这演示了如何利用Select
将日志记录不仅映射到DTO中,而且还将相关记录映射到诸如也可以完成字符串的收集或其他DTO的收集。
一旦选择了DTO,我就使用静态工厂方法将其填充到容器DTO中,以填充成功的读取或失败的读取。 (例如,可以在异常处理程序中进行设置。)或者,您可以新建一个容器类并填充属性,使用构造函数/ w参数,或者仅返回DTO列表。 EF查询中未 引用SearchResultsDTO容器。