gpt4 book ai didi

c# - 将 Expression> 中的类型转换为 Expression> (LINQ to SQL)

转载 作者:太空宇宙 更新时间:2023-11-03 12:34:01 25 4
gpt4 key购买 nike

注意:

  1. 我的应用程序 (asp.net mvc) 出于松散耦合的目的分层分离。
  2. 实体krt_Naftan 和ScrollLineDTO 具有相同的属性并在不同层中使用。我使用 Automapper 在它们之间进行转换。
  3. 我想在 LINQ to SQL(表达式树)中使用一些谓词 (x => x.DTBUHOTCHET == '01.01.2016')。

它适用于函数:

Func<ScrollLineDTO, bool> predicate = x => x.DTBUHOTCHET == '01.01.2016';
Func<krt_Naftan, bool> func = x => predicate(Mapper.Map<ScrollLineDTO>(x));

因为我无法将 func 包装到表达式树 (LINQ to SQL)//不适用于 EF6

Expression<Func<krt_Naftan, bool>> filter = x => func(x);

我尝试在表达式中转换类型(编译错误)

Expression<Func<ScrollLineDTO, bool>> predicate = x => x.DTBUHOTCHET == '01.01.2016';

Expression<Func<krt_Naftan, bool>> func = x =>predicate(Mapper.Map<ScrollLineDTO>(x));

问题:如何对表达式树语句使用转换功能?或者可能需要其他东西;)

1)索引方法(UI层)

public ActionResult Index(DateTime? period = null, int page = 1, bool asService = false, ushort initialSizeItem = 15) {
if (Request.IsAjaxRequest()) {
long recordCount;

//default
Expression<Func<ScrollLineDTO, bool>> predicate = x => x.DTBUHOTCHET == (period == null ? new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1) : period);

var result = new IndexMV() {
ListKrtNaftan = _bussinesEngage.SkipTable(page, initialSizeItem, out recordCount, predicate),
...
}
};
....

2)(BLL层)

 public IEnumerable<T> SkipTable<T>(int page, int initialSizeItem, out long recordCount, Expression<Func<T, bool>> predicate = null) {

if (predicate == null) {
//convert func types

Expression<Func<krt_Naftan, bool>> func = x => predicate(Mapper.Map<ScrollLineDTO>(x));
//wrap in func to expression (is not impossible, maybe if pass method...)
//Expression<Func<krt_Naftan, bool>> filter = x => func(x);

return (IEnumerable<T>)Mapper.Map<IEnumerable<ScrollLineDTO>>(Engage.GetSkipRows(page, initialSizeItem, out recordCount, x => x.KEYKRT, func));
}

return (IEnumerable<T>)Mapper.Map<IEnumerable<ScrollLineDTO>>(Engage.GetSkipRows<krt_Naftan, long>(page, initialSizeItem, out recordCount, x => x.KEYKRT));
}

/// <summary>
/// Return pagging part of table and general count of rows
/// </summary>
/// <typeparam name="T">Current enity</typeparam>
/// <typeparam name="TKey">Type for ordering</typeparam>
/// <param name="page">Number page</param>
/// <param name="size">Count row per one page</param>
/// <param name="recordCount"></param>
/// <param name="orderPredicate">Condition for ordering</param>
/// <param name="filterPredicate">Condition for filtering</param>
/// <param name="caсhe"></param>
/// <returns>Return definition count rows of specific entity</returns>
public IEnumerable<T> GetSkipRows<T, TKey>(int page, int size, out long recordCount, Expression<Func<T, TKey>> orderPredicate, Expression<Func<T, bool>> filterPredicate = null, bool caсhe = false) where T : class {
recordCount = GetCountRows(filterPredicate);
using (Uow = new UnitOfWork()) {
return Uow.Repository<T>().Get_all(filterPredicate, caсhe).OrderByDescending(orderPredicate).Skip((page - 1) * size).Take(size).ToList();
}
}

3)(DLL层)从db中获取数据

/// <summary>
/// Get lazy data set (with cashing or not (attr MergeOption )
/// </summary>
/// <param name="predicate">filter condition for retrieving data from source(database)</param>
/// <param name="enableDetectChanges">Compare two snapshot of data (one when retrieve data from database other when call method saveChanges(). If exists some diffrences => generate avaible SQL command</param>
/// <param name="enableTracking"></param>
/// <returns></returns>
public IQueryable<T> Get_all(Expression<Func<T, bool>> predicate = null, bool enableDetectChanges = true, bool enableTracking = true) {
/*//sync data in Db & EF (if change not tracking for EF)
((IObjectContextAdapter)_context).ObjectContext.Refresh(RefreshMode.StoreWins, _dbSet.Where(predicate));
_context.Entry(_dbSet.Where(predicate)).Reload(); EF 4.1+*/
ActiveContext.Configuration.AutoDetectChangesEnabled = enableDetectChanges;
if (predicate == null) return (enableTracking) ? _dbSet : _dbSet.AsNoTracking();
var result = (enableTracking) ? _dbSet.Where(predicate) : _dbSet.AsNoTracking().Where(predicate);

return result;
}

谢谢)

最佳答案

我找到了我需要的东西!

  1. Replace a type in an expression tree
  2. How to change a type in an expression tree?

解决方案是访问者模式(lINQ 有内置的 ExpressionVisitor 实现(С# 4.0))。

在我的例子中,实现是:

  public static Expression<Func<OutT, bool>> ConvertTypeExpression<inT, OutT>(Expression expression) where OutT : class {

var param = Expression.Parameter(typeof(OutT), "x");

var result = new CustomExpVisitor<OutT>(param).Visit(expression);

Expression<Func<OutT, bool>> lambda = Expression.Lambda<Func<OutT, bool>>(result, new[] { param });

return lambda;
}

private class CustomExpVisitor<T> : ExpressionVisitor {
ParameterExpression _param;

public CustomExpVisitor(ParameterExpression param) {
_param = param;
}

protected override Expression VisitParameter(ParameterExpression node) {
return _param;
}

protected override Expression VisitMember(MemberExpression node) {
if (node.Member.MemberType == MemberTypes.Property) {
MemberExpression memberExpression = null;

var memberName = node.Member.Name;
var otherMember = typeof(T).GetProperty(memberName);

memberExpression = Expression.Property(Visit(node.Expression), otherMember);

return memberExpression;
} else {
return base.VisitMember(node);
}
}
}

最后我得到了我搜索的功能)

var filterPredicate = PredicateExtensions.ConvertTypeExpression<ScrollLineDTO, krt_Naftan>(predicate.Body);

关于c# - 将 Expression<Func<T1, bool>> 中的类型转换为 Expression<Func<T2, bool>> (LINQ to SQL),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41692756/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com