我有LINQ查询,在这个查询中,我必须使用一个结果集进行响应,这取决于内部字段集合。我已经通过LINQ查询完成了这件事,然后是一个foreach,但是我想要避免foreach循环,并通过
List<ResultModel> result = new List<ResultModel>();
var tempResultSet = _context.MainRecordTable.Where(h => h.id)
.Select(lev => new
{
Contacts = (lev.basetable2 != null
&& lev.basetable2.basetable3 != null
&& lev.basetable2.basetable3.basetable6 != null
&& lev.basetable2.basetable3.basetable6.Any(h=>h.contact != null)
? lev.basetable2.basetable3.basetable6.Where(h=>h.contact != null).Select(h=>h.contact).Distinct() : null),
Key1 = lev.basetable5 != null ? lev.basetable5.Id : null,
Key2 = lev.basetable2 != null && lev.basetable2.basetable3 != null && lev.basetable2.basetable3.basetable4 != null ?
lev.basetable2.basetable3.basetable4.id : null
})
.Distinct()
.ToList();
foreach (var x in tempResultSet)
{
if (x.Contacts != null)
{
foreach (var contact in x.Contacts)
{
result.Add(new ResultModel
{
Key1 = x.Key1,
Key2 = x.Key2,
ContactKey = contact.id
});
}
}
else
{
result.Add(new ResultModel
{
Key1 = x.Key1,
Key2 = x.Key2
});
}
}
return result;
我最后的Linq查询如下
返回_context.baseTable1.Where(h => h.id == Id ).Select(lev =>新的{ Contact = (lev.baseTable2 != null &lev.base Table2.base.Select 3 != null &lev.base Table2.base Table3.base Table5),任何(h => h.contact != null)吗?(h => h.contact != null).GroupBy(h => h.contact: null),Key1 = lev.office != null?lev.office.id,:null,Key2 = lev.baseTable2 != null &lev.base Table2.base 3 != null &lev.base Table2.base Table3 != null!=null?Lev.base Table2.base Table3.base Table4.id: null
}).ToList().SelectMany(x =>
{
if (!x.Contact.Any())
{
return new List<FinalModel> { new FinalModel { Key1 = x.Key1, Key2 = x.Key2 } };
}
else
return x.Contact.Select(contact => new FinalModel()
{
ContactKey = contact.id,
Key1 = x.Key1,
Key2 = x.Key2
});
});
发布于 2022-07-07 12:20:44
您可以使用SelectMany
来扁平数组,例如:
List<ResultModel> result = _context.MainRecordTable.Where(h => h.id)
.Select(lev => new
{
Contacts = (lev.basetable2 != null
&& lev.basetable2.basetable3 != null
&& lev.basetable2.basetable3.basetable6 != null
&& lev.basetable2.basetable3.basetable6.Any(h=>h.contact != null)
? lev.basetable2.basetable3.basetable6.Where(h=>h.contact != null).Select(h=>h.contact).Distinct() : null),
Key1 = lev.basetable5 != null ? lev.basetable5.Id : null,
Key2 = lev.basetable2 != null && lev.basetable2.basetable3 != null && lev.basetable2.basetable3.basetable4 != null ?
lev.basetable2.basetable3.basetable4.id : null
})
.Distinct()
.ToList()
.SelectMany(x => {
if (x.Contacts == null)
return new ResultModel[]
{
Key1 = x.Key1,
Key2 = x.Key2,
};
else
return x.Contacts.Select(contact => new ResultModel()
{
Key1 = x.Key1,
Key2 = x.Key2,
ContactKey = contact.id,
}).ToArray();
})
.ToList();
在SelectMany
中,将检查是否设置了联系人列表;如果没有,则返回单个项目,否则将返回每个联系人的项目。
发布于 2022-07-07 15:37:02
我会发现,为没有联系人键的结果创建一个ResultModel
子集合和用一个联系人键为结果创建另一个子集合更容易读。我怀疑随着时间的推移,这种方法也会比一个Linq表达式更容易维护。
您可以首先对临时结果进行分组,以便一个子集合包含临时结果而没有 contacts,而另一个子集合包含临时结果(E 210E 111
联系人E 212
)。
通过使用具有适当条件的包含联系人的.ToLookup(),很容易获得这种分组。
var tempResultByContainingContacts = tempResultSet
.ToLookup(x => x.Contacts != null && x.Contacts.Any());
(我添加了&& x.Contacts.Any()
条件。如果这不适合您的用例,您可以忽略它。)
在定义了查找表之后,您有:
tempResultByContainingContacts[false]
中的tempResultByContainingContacts[true]
现在,可以根据临时结果计算一个结果子集合,而不需要 contacts。
var resultWithoutContactKey = tempResultByContainingContacts[false]
.Select(x => new ResultModel
{
Key1 = x.Key1,
Key2 = x.Key2
});
以及基于临时结果和 contacts生成的子集合。
var resultWithContactKey = tempResultByContainingContacts[true]
.SelectMany(x => x.Contacts
.Select(contact => new ResultModel
{
Key1 = x.Key1,
Key2 = x.Key2,
ContactKey = contact.id
}));
最后,将两个子集合连接起来以创建result
。
var result = resultWithoutContactKey
.Concat(resultWithContactKey)
.ToList();
注意:
一个接一个的问题更新建议
除了添加一行来验证.Select()
之外,我没有对新的主[...].baseTable5 != null
块中的逻辑进行任何更改。
我建议拆分临时子集合并创建结果子集合,遵循我前面描述的模式:
var tempResult = _context.baseTable1
.Where(h => h.id == Id)
.Select(lev => new
{
Contact =
lev.baseTable2 != null &&
lev.baseTable2.baseTable3 != null &&
lev.baseTable2.baseTable3.baseTable5 != null && // this line was added
lev.baseTable2.baseTable3.baseTable5
.Any(h => h.contact != null)
? lev.baseTable2.baseTable3.baseTable5
.Where(h => h.contact != null)
.GroupBy(h => h.contact)
.Select(c => c.FirstOrDefault().contact)
: null,
Key1 =
lev.office != null
? lev.office.id,
: null,
Key2 =
lev.baseTable2 != null &&
lev.baseTable2.baseTable3 != null &&
lev.baseTable2.baseTable3.baseTable4 != null
? lev.baseTable2.baseTable3.baseTable4.id
: null
})
.ToList();
var tempResultByContainingContacts = tempResult
.ToLookup(x => x.Contact != null && x.Contact.Any());
var resultWithoutContactKey = tempResultByContainingContacts[false]
.Select(x => new FinalModel
{
Key1 = x.Key1,
Key2 = x.Key2
});
var resultWithContactKey = tempResultByContainingContacts[true]
.SelectMany(x => x.Contact
.Select(contact => new FinalModel
{
ContactKey = contact.id,
Key1 = x.Key1,
Key2 = x.Key2
}));
var result = resultWithoutContactKey
.Concat(resultWithContactKey)
.ToList();
return result;
如果可能的话,我还建议简化新的主.Select()
块。不过,我不确定在查询数据库时是否可以翻译?.
符号。如果不能,请忽略以下建议:
var tempResult = _context.baseTable1
.Where(h => h.id == Id)
.Select(lev => new
{
Contact = lev.baseTable2?.baseTable3?.baseTable5?
.Where(h => h.contact != null)
.GroupBy(h => h.contact)
.Select(c => c.FirstOrDefault().contact),
Key1 = lev.office?.id,
Key2 = lev.baseTable2?.baseTable3?.baseTable4?.id
})
.ToList();
https://stackoverflow.com/questions/72897523
复制相似问题