C# 如何整合表达式<;Func<&燃气轮机&燃气轮机;清理我的Linq到实体查询?
我想使用C# 如何整合表达式<;Func<&燃气轮机&燃气轮机;清理我的Linq到实体查询?,c#,asp.net,linq,entity-framework,linq-to-sql,C#,Asp.net,Linq,Entity Framework,Linq To Sql,我想使用Expression方法来清理我的DTO Linq to Query Selects,这样就不会使它们比现有的增长更多。对于如何将它们集成到我自己的项目中,我仍然有点困惑 例如: public IQueryable<ExampleDTO> SelectDTO() { var repository = new ExampleUDCRepository(); return db.Example .Select(v => new Example
Expression
方法来清理我的DTO Linq to Query Selects,这样就不会使它们比现有的增长更多。对于如何将它们集成到我自己的项目中,我仍然有点困惑
例如:
public IQueryable<ExampleDTO> SelectDTO()
{
var repository = new ExampleUDCRepository();
return db.Example
.Select(v => new ExampleDTO
{
ExampleID = v.ExampleID,
MasterGroupID = v.MasterGroupID,
//...etc
ExampleUDCs = db.ExampleUDCs
.Where(vudc => vudc.ExampleID == v.ExampleID)
.AsEnumerable()
.Select(vudc => new ExampleDCDTO
{
ExampleID = vudc.ExampleID,
UDCHeadingID = vudc.UDCHeadingID,
UDCValue = vudc.UDCValue
})
});
public IQueryable SelectDTO()
{
var repository=newexampleudcrespository();
返回db.Example
.选择(v=>newexampledto
{
ExampleID=v.ExampleID,
MasterGroupID=v.MasterGroupID,
//…等等
ExampleUDCs=db.ExampleUDCs
.Where(vudc=>vudc.ExampleID==v.ExampleID)
.可计算的()
.选择(vudc=>new ExampleDCDTO
{
ExampleID=vudc.ExampleID,
UDCHeadingID=vudc.UDCHeadingID,
UDCValue=vudc.UDCValue
})
});
我的其他一些DTO设置和返回方法甚至更大、更草率
我真正想做的是这样的事情:
public IQueryable<ExampleDTO> SelectDTO()
{
var repository = new ExampleUDCRepository();
return db.Example
.Select(v => new ExampleDTO
{
ExampleID = v.ExampleID,
MasterGroupID = v.MasterGroupID,
//...etc
ExampleUDCs = new ExampleUDCsRepository().SelectDTO(v);
// SelectDTO(Example v) in that repository would call
// any other SelectDTO it might need and so forth
});
public IQueryable SelectDTO()
{
var repository=newexampleudcrespository();
返回db.Example
.选择(v=>newexampledto
{
ExampleID=v.ExampleID,
MasterGroupID=v.MasterGroupID,
//…等等
ExampleUDCs=新建ExampleUDCsRepository()。选择DTO(v);
//选择存储库中的DTO(示例v)将调用
//它可能需要的任何其他选择,等等
});
问题是,Linq不知道如何将这样的方法转换成SQL语句,这就是Expression
方法用来传递此类内容的地方
我对Expression
的理解是有限的,而且我还没有找到任何文档可以让我想做的更清楚
将
表达式
集成到我的DTO中的最佳方法是什么?因此,首先我们需要一些辅助方法。我们将从这个简单的类开始,用另一个表达式替换一个表达式的所有实例:
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
接下来,我们将创建一个扩展方法来使用它:
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
最后,我们将创建一个将两个表达式组合在一起的Combine
方法。它将使用一个表达式从一个值计算中间结果,然后使用第一个值和中间结果来确定最终结果
public static Expression<Func<TFirstParam, TResult>>
Combine<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<TFirstParam, TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TFirstParam), "param");
var newFirst = first.Body.Replace(first.Parameters[0], param);
var newSecond = second.Body.Replace(second.Parameters[0], param)
.Replace(second.Parameters[1], newFirst);
return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}
现在,我们可以调用此SelectDTO
方法来生成计算中间值的表达式,并将它与使用它的另一个表达式组合起来:
public IQueryable<ExampleDTO> SelectDTO()
{
ExampleUDCRepository repository = new ExampleUDCRepository();
return db.Example
.Select(repository.SelectDTO().Combine((v, exampleUDCs) =>
new ExampleDTO()
{
ExampleID = v.ExampleID,
MasterGroupID = v.MasterGroupID,
ExampleUDCs = exampleUDCs,
}));
}
这是一个有趣且描述得很好的问题,但在粘贴代码时请格外小心。IDE的标签转换为4*空格,在第一次“粘贴”时并不总是真正可读。我对其进行了一点修剪,没有进行任何实际更改,而且不会像之前那样伤害眼睛。但是,当然,与所有化妆品一样,这只是我的个人操作inion和small suggestion;)我唯一的另一个问题是那里的.Invoke()方法。我的SelectDTO(在第一个方法中被调用的一个)是否需要更改?例如表达式SelectDTO(示例五)
?我无法让该实现按您的方式工作。说Invoke()具有无效的参数。Thanks@nzondlo然后不要使用LINQKit解决方案,使用其他解决方案。
public IQueryable<ExampleDTO> SelectDTO()
{
ExampleUDCRepository repository = new ExampleUDCRepository();
return db.Example
.Select(repository.SelectDTO().Combine((v, exampleUDCs) =>
new ExampleDTO()
{
ExampleID = v.ExampleID,
MasterGroupID = v.MasterGroupID,
ExampleUDCs = exampleUDCs,
}));
}
public IQueryable<ExampleDTO> SelectDTO()
{
ExampleUDCRepository repository = new ExampleUDCRepository();
var generateUDCExpression = repository.SelectDTO();
return db.Example
.AsExpandable()
.Select(v =>
new ExampleDTO()
{
ExampleID = v.ExampleID,
MasterGroupID = v.MasterGroupID,
ExampleUDCs = generateUDCExpression.Invoke(v),
});
}