I have an entity table with below model
public class VulnerabilityImportFileLog
{
public Collection<Vulnerability> Vulnerability { get; set; }
}
Trying to return an string value using the select statement in the entity framework query
var vulnerabilityImportFileLogSelect = vulnerabilityImportFileLogQuery
.Select(vulnerabilityImportFileLog =>
new VulnerabilityImportedScansListViewDto
{
AssetName = vulnerabilityImportFileLog.Vulnerability.Select(y =>
{
if (y.AssetHostIPOrDomain.HostIPAssetId.HasValue)
return y.AssetHostIPOrDomain.HostIPAsset.Title;
else if (y.AssetHostIPOrDomain.DomainAssetId.HasValue)
return y.AssetHostIPOrDomain.DomainAsset.Title;
else
return y.AssetHostIPOrDomain.HostIPOrDomain;
}
).Distinct().ToList()
});
Where AssetName
is of type List<string>
and getting an exception as A lamda expression with a statement body cannot be converted to an expression tree
An suggested answer was to use AsEnumerable()
, but even that not solved the issue.
CodePudding user response:
You can solve the problem by using linq query syntax with 'let' keyword:
AssetName = (from y in vulnerabilityImportFileLog.Vulnerability
let resultString = y.AssetHostIPOrDomain.HostIPAssetId.HasValue
? y.AssetHostIPOrDomain.HostIPAsset.Title
: y.AssetHostIPOrDomain.DomainAssetId.HasValue
? y.AssetHostIPOrDomain.DomainAsset.Title
: y.AssetHostIPOrDomain.HostIPOrDomain
select resultString
)
.ToList()
.Distinct();
CodePudding user response:
Assuming vulnerabilityImportFileLogQuery is an IQueryable<vulnerabilityImportFileLog>
then a typical way to fetch details from the associated Vulnerability relations would be via a SelectMany
. Given you need to do substitution depending on what is available, one option would be to do a double-projection. The first pass selects and materializes just the details we want to inspect, then the second pass composes the results.
vulnerabilityImportFileLogQuery.SelectMany(x => new
{
x.Vulnerability.AssetHostIpOrDomain.HostIpOrDomain,
HostIpAssetTitle = x.Vulnerability.AssetHostIpOrDomain.HostIpAsset.Title,
DomainAssetTitle = x.Vulnerability.AssetHostIpOrDomain.DomainAsset.Title
}).ToList()
.Select(x => x.HostIpAssetTitle ?? DomainAssetTitle ?? HostIpOrDomain)
.Distinct()
.ToList();
What this essentially does is fetch the 3 values, our default HostIpOrDomain value, and the Titles from the HostIpAsset and DomainAsset if they are available. EF will return #null if the entities aren't associated or the Title is #null. This query is materialized using the ToList
, then from that we Select the title to use based on a null check, before taking our Distinct set.
Hopefully that gives you a few ideas as a starting point.