如何在 DTO 中正确存储多个结果?
How to correctly store a number of results in a DTO?
我已将存储过程附加到数据库,它应该 return 只需简单搜索即可得到结果。查询被添加到我的实体并调用常规方法。我面临的问题是将此过程的结果作为列表存储到特定的 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 中,以便在 return.
上传递
对于 EF,您将希望利用 Select()
将实体映射到您的 DTO,但您需要考虑 DTO 的整个结构。例如,"Logs" 数据结构将由什么组成?它是单个字符串值、字符串列表还是日志记录列表?
使用 Select()
你需要利用 属性 setter,而不是接受实体的构造函数。
所以这样的模式:
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();
使用构造函数查看您的示例:
public class Dto
{
public 字符串字段 { 得到;私有集; }
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();
使用 select 之前的额外 ToList()
,调用将起作用,因为 EF 将执行查询和 return 实体列表,然后 Select()
将作为 Linq2Object 查询执行。你应该避免这种情况的原因是因为 EF 将从实体 select all 属性,我们应该只拉回我们关心的属性。如果您的 Dto 构造函数群体开始迭代相关实体,也很容易陷入 lazy-load 性能陷阱。使用 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;
}
这假设日志条目有作业、名称、开始、结束 date/times,然后是 "lines" 或要显示为 "Logs" 的条目列表。 (其中 Log table 有一个相关的 LogLine table 例如与一行或多行)这演示了如何利用 Select
不仅将日志记录映射到 DTO,而且将相关记录映射到字符串集合之类的东西,或者也可以完成其他 DTO 的集合。
一旦它 select 成为 DTO,我让它使用静态工厂方法填充容器 DTO 以填充成功读取或失败读取。 (例如,可以在异常处理程序中设置。)或者,您可以只新建一个容器 class 并填充属性,使用构造函数 /w 参数,或者只 return DTO 列表。 SearchResultsDTO 容器在 EF 查询中未被引用。
我已将存储过程附加到数据库,它应该 return 只需简单搜索即可得到结果。查询被添加到我的实体并调用常规方法。我面临的问题是将此过程的结果作为列表存储到特定的 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 中,以便在 return.
上传递对于 EF,您将希望利用 Select()
将实体映射到您的 DTO,但您需要考虑 DTO 的整个结构。例如,"Logs" 数据结构将由什么组成?它是单个字符串值、字符串列表还是日志记录列表?
使用 Select()
你需要利用 属性 setter,而不是接受实体的构造函数。
所以这样的模式:
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();
使用构造函数查看您的示例: public class Dto { public 字符串字段 { 得到;私有集; }
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();
使用 select 之前的额外 ToList()
,调用将起作用,因为 EF 将执行查询和 return 实体列表,然后 Select()
将作为 Linq2Object 查询执行。你应该避免这种情况的原因是因为 EF 将从实体 select all 属性,我们应该只拉回我们关心的属性。如果您的 Dto 构造函数群体开始迭代相关实体,也很容易陷入 lazy-load 性能陷阱。使用 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;
}
这假设日志条目有作业、名称、开始、结束 date/times,然后是 "lines" 或要显示为 "Logs" 的条目列表。 (其中 Log table 有一个相关的 LogLine table 例如与一行或多行)这演示了如何利用 Select
不仅将日志记录映射到 DTO,而且将相关记录映射到字符串集合之类的东西,或者也可以完成其他 DTO 的集合。
一旦它 select 成为 DTO,我让它使用静态工厂方法填充容器 DTO 以填充成功读取或失败读取。 (例如,可以在异常处理程序中设置。)或者,您可以只新建一个容器 class 并填充属性,使用构造函数 /w 参数,或者只 return DTO 列表。 SearchResultsDTO 容器在 EF 查询中未被引用。