Join in System.Linq.Dynamic.Core

63 Views Asked by At

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
0

There are 0 best solutions below