I'm trying to perform a dynamic join operation on IQueryable
entities based on certain conditions, and then project the result into a dynamic type with a specific structure. Specifically, I want to create a dynamic join between a main table and related tables based on their relationships, and then select specific columns from main table.
In a simple way, I want to achieve this query but in a dynamic way cause the type is determined at runtime
private IQueryable FilterPropertiesBasedOnViewModel(IQueryable data, Type modelType, Type viewModelType, Dictionary<string, (Type, Type)> modelTypeMapping)
{
var viewModelProperties = viewModelType.GetProperties().Select(p => p.Name).ToList();
var modelProperties = modelType.GetProperties().Where(p => viewModelProperties.Contains(p.Name)).ToList();
if (modelProperties.Any())
{
var selectExpression = new List<string>();
foreach (var propertyInfo in modelProperties)
{
if (Nullable.GetUnderlyingType(propertyInfo.PropertyType) == typeof(Guid))
{
var (relatedType, relatedKeyType) = modelTypeMapping[propertyInfo.Name];
var relatedTableName = relatedType.Name;
var outerKeySelector = $"it.{propertyInfo.Name}?";
var innerKeySelector = $"Oid";
var resultSelector = $"new(outer.{propertyInfo.Name} as {propertyInfo.Name})";
// Apply Join using System.Linq.Dynamic.Core
data = data.Join(
GetTypedDbSet(relatedType),
outerKeySelector,
innerKeySelector,
resultSelector
);
}
// Add the property to the select expression
selectExpression.Add($"{propertyInfo.Name} as {propertyInfo.Name}");
}
var finalSelectExpression = string.Join(", ", selectExpression);
// Project the data to include only common properties
return data.Select($"new ({finalSelectExpression})");
}
else
{
return data;
}
}
Expecting a query like this
select
b.Name,
a.Name as Account,
c.Name as Country,
p.Name as Province,
sp.Name as SubProvince
from
dbo.Branch b
left join
dbo.Account a on a.Oid = b.Account
left join
dbo.Country c on c.Oid = b.Country
left join
dbo.Province p on p.Oid = b.Province
left join
dbo.SubProvince sp on sp.Oid = b.SubProvince