我有 3 个通过外键链接的表:ChangeSet、ObjectChanges、PropertyChanges。这些表彼此之间具有一对多关系。我需要加入并投影并将结果扁平化为匿名类型。
我们在数据层使用 Entity Framework ,我本质上需要使用 linq 进行以下查询。
select c.Id as ChangeSetId,
c.Timestamp,
c.Author_Id,
u.Name as [User],
o.id as ObjectChangeId,
o.TypeName,
o.ObjectReference as EntityId,
o.DisplayName,
p.Id as PropertyChangeId,
p.PropertyName,
p.ChangeType,
p.OriginalValue,
p.Value
from ChangeSets c
inner join ObjectChanges o
on c.Id = o.ChangeSetId
left join PropertyChanges p
on p.ObjectChangeId = o.Id
inner join Users u
on u.Id = c.Author_Id
order by c.id desc
所讨论的方法看起来像这样:
GetAllWhereExpression(Expression<Func<ChangeSet, bool>> expression)
本例中的表达式可能是Where o.EntityId = [Some Value] and c.TimeStamp > X and < Y。
我在 linq 中感觉非常接近以下内容,但无法弄清楚如何注入(inject)表达式:(.GetRepository().Entities 基本上是 DbSet)
var foo = from c in _uow.GetRepository<ChangeSet>().Entities
join o in _uow.GetRepository<ObjectChange>().Entities on c.Id equals o.ChangeSetId
join p in _uow.GetRepository<PropertyChange>().Entities on o.Id equals p.ObjectChangeId
where expression // This Line Not Valid
select new
{
ChangeSetId = c.Id,
Timestamp = c.Timestamp,
User = c.User.DisplayName,
EntityType = o.TypeName,
EntityValue = o.DisplayName,
Property = p.PropertyName,
OldValue = p.OriginalValue,
NewValue = p.Value
};
我更喜欢使用 Lambda 语法,但我不知道如何构建它。我知道我需要 SelectMany 来投影和展平结果,但我不知道如何在子集合的匿名类型中使用它们:
var queryable = _uow.GetRepository<ChangeSet>().Entities // This is basically the DbSet<ChangeSet>()
.Where(expression)
.SelectMany(c => new
{
ChangeSetId = c.Id,
Timestamp = c.Timestamp,
User = c.User.DisplayName,
EntityType = c.ObjectChanges.SelectMany(o => o.TypeName), //Doesn't work, turns string into char array
//PropertyName = c. this would be a 1 to many on the entity
}
)
如何制作 linq 以产生与 sql 查询基本相同的结果?
最佳答案
方法语法如下。
_uow.GetRepository<ChangeSet>().Entities
.Where(expression)
.Join(_uow.GetRepository<ObjectChanges>().Entities, cs => cs.Id, oc => oc.ChangeSetId,
(cs, oc) => new { cs, oc })
.Join(_uow.GetRepository<PropertyChanges>().Entities, outer => outer.oc.Id, pc => pc.ObjectChangeId,
(outer, pc) => new { cs = outer.cs, oc = outer.cs, pc })
.Join(_uow.GetRepository<User>().Entities, outer => outer.cs.Author_Id, u => u.Id,
(outer, u) => new {
ChangeSetId = outer.cs.Id,
Timestamp = outer.cs.Timestamp,
User = u.DisplayName,
EntityType = outer.oc.TypeName,
EntityValue = outer.oc.DisplayName,
Property = outer.pc.PropertyName,
OldValue = outer.pc.OriginalValue,
NewValue = outer.pc.Value
})
关于c# - 如何使用 Linq 或 Lambda 连接一对多表并将扁平化结果投影为匿名类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42430915/