Reputation: 11
I am planning to implement a dynamic advanced search page, the way it works is that the user selects the names of the tables and columns he is interested in and then types the desired phrase. If the selected tables are related, they are joined and the expression or dates are applied as restrictions on the records, and then the result is returned. Finally, the columns that are allowed are selected and the result is sent to the client for display. These allowed columns are stored in a resource file with the extension resx.
public (IEnumerable, int, int) GetSearchResultListAsync(List<SearchDTO> filterList, int pageId = 1)
{
try
{
// Create a new queryable for the first table
var entityTypes = _dbContext.Model.GetEntityTypes();
var entityType = entityTypes.FirstOrDefault(t => t.ClrType.Name == filterList[0].TableName)?.ClrType;
if (entityType == null)
{
return (null, 0, 0);
}
Type dbSetType = typeof(DbSet<>).MakeGenericType(entityType);
var constructor = dbSetType.GetConstructor(new[] { typeof(DbContext) });
if (constructor != null)
{
var query = (IQueryable<object>)constructor.Invoke(new object[] { _dbContext });
//var query = (IQueryable<object>)Activator.CreateInstance(typeof(DbSet<>).MakeGenericType(entityType), _dbContext);
// Join the remaining tables dynamically based on the table names
for (int i = 1; i < filterList.Count; i++)
{
var joinEntityType = entityTypes.FirstOrDefault(t => t.ClrType.Name == filterList[0].TableName)?.ClrType;
if (entityType == null)
{
return (null, 0, 0);
}
var joinEntityQuery = (IQueryable<object>)Activator.CreateInstance(typeof(DbSet<>).MakeGenericType(joinEntityType), _dbContext);
query = query.Join(joinEntityQuery.ToList(),
x => x.GetType().GetProperty($"{filterList[i - 1].TableName}.{filterList[i - 1].TableName}Id").GetValue(x),
y => y.GetType().GetProperty($"{filterList[i].TableName}.{filterList[i].TableName}Id").GetValue(y),
(x, y) => x);
}
// Apply the conditions dynamically based on the column names and conditions
for (int i = 0; i < filterList.Count; i++)
{
if (!string.IsNullOrEmpty(filterList[i].searchPhrase))
{
var parameter = Expression.Parameter(entityType, "x");
var condition = Expression.Call(
typeof(string).GetMethod("Contains", new[] { typeof(string) }),
Expression.PropertyOrField(parameter, filterList[i].ColumnName),
Expression.Constant(filterList[i].searchPhrase)
);
var lambda = Expression.Lambda<Func<object, bool>>(condition, parameter);
query = query.Where(lambda);
}
if (filterList[i].searchDateFrom.HasValue)
{
}
}
// Select the specified columns dynamically
ResourceManager resourceManager = new ResourceManager(typeof(TablePropertiesResources));
var columnNames = resourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, true)
.OfType<DictionaryEntry>()
.Select(entry => entry.Key.ToString())
.ToList();
var selectColumns = columnNames.ToArray();
var selectedData = query
.Select(x => new
{
// Dynamically select the desired properties
Result = selectColumns.ToDictionary(column => column, column => x.GetType().GetProperty(column).GetValue(x))
})
.ToList();
// Convert the anonymous type to a dynamic object
//var dynamicSelectedData = selectedData
// .Select(x =>
// {
// IDictionary<string, object> expando = new ExpandoObject();
// foreach (var kvp in x.Result)
// {
// expando.Add(kvp.Key, kvp.Value);
// }
// return (dynamic)expando;
// })
// .ToList();
// Execute the query
int skip = (pageId - 1) * 10;
int count = selectedData.Count();
double tempCount = count;
int pageCount = (int)Math.Ceiling(tempCount / 10.0);
//_dbContext.SaveChanges();
var result = selectedData
.Skip(skip).Take(10);
if (result.Count() == 0)
{
return (null, 0, 0);
}
//var tuple = new Tuple<IAsyncEnumerable<ResultNamehDTO>, int>(result, pageCount);
return (result, pageCount, count);
}
else
{
return (null, 0, 0);
}
}
catch (Exception e)
{
_manualLog.LogAsync(
"Error",
null,
e.Message,
e.StackTrace,
"LetterService",
"GetLetterListAsync");
return (null, 0, 0);
}
}
public class SearchDTO
{
public string TableName { get; set; }
public string ColumnName { get; set; }
public string searchPhrase { get; set; } = string.Empty;
public DateTimeOffset? searchDateFrom { get; set; }
public DateTimeOffset? searchDateTo { get; set; }
//public int dateType { get; set; } = 20;
public int Include { get; set; } = 1;
}
I use blazor. Now the problem is that the constructor variable is not filled. It's value is null and do not enter in if block. Please guide me how to fix this problem. Thankful
Upvotes: 0
Views: 78