我有一个实体框架实体
public class Entiy
{
public string EntityProperty1 { get; set; }
public string EntityProperty2 { get; set; }
public string EntityProperty3 { get; set; }
public Guid? SomeId { get; set; }
}
还有一个OtherObject和一个DTO,它包含的属性与其他类相同。
public class OtherObject
{
public string OtherObjectProperty1 { get; set; }
public string OtherObjectProperty2 { get; set; }
public string OtherObjectProperty3 { get; set; }
public Guid SomeId { get; set; }
}
public class DTO
{
public string EntityProperty1 { get; set; }
public string EntityProperty2 { get; set; }
public string EntityProperty3 { get; set; }
public string OtherObjectProperty1 { get; set; }
public string OtherObjectProperty2 { get; set; }
public string OtherObjectProperty3 { get; set; }
}
在我的服务类中,我获得了我的实体的IQueryable,并且我发送了一个包含可枚举的OtherObject的参数。当我只想使用实体属性创建DTO时,它工作正常。
public IEnumerable<DTO> GetDtos(IEnumerable<OtherObject> otherObjects)
{
return _someRepository.GetAll()
.Where(a => otherObjects.Select(b => b.SomeId).Contains(a.SomeId))
.Select(d => new DTO()
{
EntityProperty1 = d.EntityProperty1
EntityProperty2 = d.EntityProperty2
EntityProperty3 = d.EntityProperty3
})
.ToList();
}
但是,我还想加入我的OtherObject类的一些属性。如果我做以下
public IEnumerable<DTO> GetDtos(IEnumerable<OtherObject> otherObjects)
{
return _someRepository.GetAll()
.Where(a => otherObjects.Select(b => b.SomeId).Contains(a.SomeId))
.Select(d => new DTO()
{
EntityProperty1 = d.EntityProperty1
EntityProperty2 = d.EntityProperty2
EntityProperty3 = d.EntityProperty3
OtherObjectEntity1 = otherObjects.FirstOrDefault(a => a.SomeId == d.SomeId).OtherObjectEntity1
})
.ToList();
}
我收到以下错误:&#34;无法创建XXX类型的常量值。在此上下文中仅支持原始类型或枚举类型&#34;
答案 0 :(得分:0)
您是否尝试使用Join而不是Where? 它看起来像这样:
_someRepository.GetAll()
.Join(otherObjects, a => a.SomeId, b => b.SomeId, (d, e) => new DTO
{
EntityProperty1 = d.EntityProperty1
EntityProperty2 = d.EntityProperty2
EntityProperty3 = d.EntityProperty3
OtherObjectEntity1 = e.OtherObjectEntity1
})
.ToList();
在我看来,它比你的实施更有效率。
修改强>
感谢您的评论,我使用数据库检查了查询,但它无效。 我决定修改查询,如果你想使用Join:)
var ids = otherObjects.Select(i => i.Id);
// When
var results = repository.GetAll()
.Where(a => ids.Contains(a.Id))
.ToList()
.Join(otherObjects, a => a.Id, b => b.Id, (a, b) => new SimpleDto
{
Id = a.Id,
Name = a.Name,
Attribute = b.Attribute
})
.ToList();
答案 1 :(得分:0)
最简单的方法是在Where子句之后做一个ToList,然后再进行DTO投影。做一个早期的ToList会过度选择存储库的所有列,这对性能不利。
另一个选项,首先实现前三列..
var result =
someRepository.GetAll()
.Where(a => otherObjects.Select(b => b.SomeId).Contains(a.SomeId))
.Select(d => new DTO()
{
EntityProperty1 = d.EntityProperty1
EntityProperty2 = d.EntityProperty2
EntityProperty3 = d.EntityProperty3
}).
.ToList()
..然后重新投影DTO:
result = result(d =>
new DTO() {
EntityProperty1 = d.EntityProperty1,
EntityProperty2 = d.EntityProperty2,
EntityProperty3 = d.EntityProperty3,
OtherObjectEntity1 = otherObjects.FirstOrDefault(a => a.SomeId == e.SomeId).OtherObjectEntity1
}
另一种方法是在IQueryable上使用IQueryable。这将在SELECT语句中生成子查询。
public IEnumerable<DTO> GetDtos(IQueryable<OtherObject> otherObjects)
{
return _someRepository.GetAll()
.Where(a => otherObjects.Select(b => b.SomeId).Contains(a.SomeId))
.Select(d => new DTO()
{
EntityProperty1 = d.EntityProperty1
EntityProperty2 = d.EntityProperty2
EntityProperty3 = d.EntityProperty3,
OtherObjectEntity1 = otherObjects.FirstOrDefault(a => a.SomeId == e.SomeId).OtherObjectEntity1
})
.ToList();
}
或者使用join(Milosz Wieczorek&#39; s answer),它比子查询更有效。
答案 2 :(得分:0)
您可以通过向第一个查询添加另一个选择来添加其他对象的属性
public IEnumerable<DTO> GetDtos(IQueryable<OtherObject> otherObjects)
{
var ids = otherObjects.Select(x => x.SomeId);
return _someRepository.GetAll()
.Where(x => ids.Contains(x.SomeId)
.ToList()
.Select(x =>
new DTO()
{
EntityProperty1 = x.EntityProperty1,
EntityProperty2 = x.EntityProperty2,
EntityProperty3 = x.EntityProperty3,
OtherObjectEntity1 = otherObjects.FirstOrDefault(p => p.SomeId == x.SomeId).OtherObjectEntity1
};
}
我也提取了其他对象&#39; ids到局部变量以优化查询一点点。