我有一個 efcore 擴展,你可以在下面找到。它允許我選擇使用屬性路徑作為字串:
_dbContext.MyModel.Select("Name")
代替
_dbContext.MyModel.Select(x => x.Name)
此選擇回傳IQueryable<string>
. 另外我想回傳模型的 ID。如果沒有擴展,它看起來像這樣:
_dbContext.MyModel.Select(x => new { Id = x.Id, Name = x.Name });
我希望能夠打電話,例如:
_dbContext.MyModel.Select("Name", withId: true)
并回傳{ Id = x.Id, Name = x.Name }
。Id 的源型別可以是字串或 Guid。目標型別應該是字串。知道如何在下面的實作中實作這一目標嗎?擴展也可以回傳 { string?, string }, string? 是身份。
Efcore 擴展:
public static IQueryable<string> SelectFromPropertyPath<T>(this IQueryable<T> query, string propertyPath)
{
var parameter = Expression.Parameter(typeof(T), "e");
var property = MakePropPath(parameter, propertyPath);
if (property.Type != typeof(string))
{
if (property.Type != typeof(object))
{
property = Expression.Convert(property, typeof(object));
}
property = Expression.Call(_toStringMethod, property);
}
var lambda = Expression.Lambda<Func<T, string>>(property, parameter);
return query.Select(lambda);
}
private static Expression MakePropPath(Expression objExpression, string path)
=> path.Split('.').Aggregate(objExpression, Expression.PropertyOrField);
private static readonly MethodInfo _toStringMethod = typeof(Convert).GetMethods()
.Single(m =>
m.Name == nameof(Convert.ToString) && m.GetParameters().Length == 1 &&
m.GetParameters()[0].ParameterType == typeof(object)
);
uj5u.com熱心網友回復:
以下擴展選擇Value
并Id
基于屬性名稱和回傳IQueryable<ValueWithId>
,稍后可用于過濾、分組、實作等。
var query1 = _dbContext.MyModel.Select("Name");
var query2 = _dbContext.MyModel.Select("Name", "OtherId");
和實作:
public static class QueryableExtensions
{
public class ValueWithId
{
public string Id { get; set; }
public string Value { get; set; }
}
public static IQueryable<ValueWithId> Select<T>(this IQueryable<T> query, string valuePath, string idPath = "Id")
{
var parameter = Expression.Parameter(typeof(T), "e");
var idProperty = MakePropPath(parameter, idPath);
var valueProperty = MakePropPath(parameter, valuePath);
idProperty = EnsureString(idProperty);
valueProperty = EnsureString(valueProperty);
var body = Expression.MemberInit(Expression.New(_valueWithIdConstructor),
Expression.Bind(_idProp, idProperty),
Expression.Bind(_valueProp, valueProperty));
var lambda = Expression.Lambda<Func<T, ValueWithId>>(body, parameter);
return query.Select(lambda);
}
static Expression MakePropPath(Expression objExpression, string path)
{
return path.Split('.').Aggregate(objExpression, Expression.PropertyOrField);
}
private static Expression EnsureString(Expression expression)
{
if (expression.Type == typeof(string))
return expression;
if (expression.Type != typeof(object))
expression = Expression.Convert(expression, typeof(object));
expression = Expression.Call(_toStringMethod, expression);
return expression;
}
private static MethodInfo _toStringMethod = typeof(Convert).GetMethods()
.Single(m =>
m.Name == nameof(Convert.ToString) && m.GetParameters().Length == 1 &&
m.GetParameters()[0].ParameterType == typeof(object)
);
private static readonly ConstructorInfo _valueWithIdConstructor = typeof(ValueWithId).GetConstructors().Single();
private static readonly PropertyInfo _idProp = typeof(ValueWithId).GetProperty(nameof(ValueWithId.Id)) ?? throw new InvalidOperationException();
private static readonly PropertyInfo _valueProp = typeof(ValueWithId).GetProperty(nameof(ValueWithId.Value)) ?? throw new InvalidOperationException();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/498019.html
上一篇:Linq通過將Id與具有id的物件串列進行比較來獲取串列
下一篇:LINQ按年份分組形成樹形視圖