C# 是否有一种替代LINQ let操作符的方法不影响性能?

C# 是否有一种替代LINQ let操作符的方法不影响性能?,c#,linq,linq-to-entities,C#,Linq,Linq To Entities,我有一个LINQ to实体查询,它使用select将原始数据从db转换为对象,并在过程中执行一些计算。这些计算重复了几次,所以我尝试重构LINQ以使用let。然而,在这样做的过程中,性能会受到极大的影响。是否有一种替代LET的方法,我可以仅用于代码的可重用性,而不影响性能 var defaultHours = 40; var defaultOldPersonPoints = 100; var defaultYoungPersonPoints = 50; // Example with no l

我有一个LINQ to实体查询,它使用select将原始数据从db转换为对象,并在过程中执行一些计算。这些计算重复了几次,所以我尝试重构LINQ以使用let。然而,在这样做的过程中,性能会受到极大的影响。是否有一种替代LET的方法,我可以仅用于代码的可重用性,而不影响性能

var defaultHours = 40;
var defaultOldPersonPoints = 100;
var defaultYoungPersonPoints = 50;

// Example with no let but lots of ugly, unreadable, redundant code
var exampleNoLet =
    (from p in people
     join op in otherPeople
         on p.PersonId equals op.PersonId into inner
     from outer in inner.DefaultIfEmpty(null)
     select new
     {
         AllocatedPoints = (p.PersonTypeId == (int)PersonType.Old
                            ? defaultOldPersonPoints
                            : p.PersonTypeId == (int)PersonType.Young
                            ? defaultYoungPersonPoints : 0)
                            + (int)(
                            (p.PersonTypeId == (int)PersonType.Old
                            ? defaultOldPersonPoints
                            : p.PersonTypeId == (int)PersonType.Young
                            ? defaultYoungPersonPoints : 0)
                            * (p.ContractedHours.HasValue
                            ? (p.ContractedHours.Value - defaultHours) / defaultHours : 0))
     });


// Using the LET allows me to clean up the code somewhat but causes a massive performance hit
var exampleUsingLet =
    (from p in people
     join op in otherPeople
         on p.PersonId equals op.PersonId into inner
     from outer in inner.DefaultIfEmpty(null)
     let defaultPoints = p.PersonTypeId == (int)PersonType.Old
                            ? defaultOldPersonPoints
                            : p.PersonTypeId == (int)PersonType.Young
                            ? defaultYoungPersonPoints : 0
     let contractedHourRatio = p.ContractedHours.HasValue 
                            ? (p.ContractedHours.Value - defaultHours) / defaultHours : 0
     select new
     {
         AllocatedPoints = defaultPoints + (int)(defaultPoints * contractedHourRatio)
     });

如果查询性能是问题,那么考虑将其移动到LINQ到对象。例如,目前,在投影中除了p没有使用任何东西。我不清楚为什么要做一个看起来像是左外连接的事情,事实上,你可以这样做:

var queryBase = from p in people
                join op in otherPeople
                on p.PersonId equals op.PersonId into inner
                from outer in inner.DefaultIfEmpty(null)
                select p;

var query = from p in queryBase.AsEnumerable() // <=== switch to LINQ-to-Objects
            let defaultPoints = p.PersonTypeId == (int)PersonType.Old
                        ? defaultOldPersonPoints
                        : p.PersonTypeId == (int)PersonType.Young
                        ? defaultYoungPersonPoints : 0
            let contractedHourRatio = p.ContractedHours.HasValue 
                        ? (p.ContractedHours.Value - defaultHours) / defaultHours : 0
            select new
            {
                AllocatedPoints = defaultPoints + (int)(defaultPoints * contractedHourRatio)
            });
在这里,SQL查询应该非常简单;所有复杂的工作都是在LINQtoObjor中执行的。

< P>如果查询性能是问题,那么考虑将其移动到LINQ到对象。例如,目前,在投影中除了p没有使用任何东西。我不清楚为什么要做一个看起来像是左外连接的事情,事实上,你可以这样做:

var queryBase = from p in people
                join op in otherPeople
                on p.PersonId equals op.PersonId into inner
                from outer in inner.DefaultIfEmpty(null)
                select p;

var query = from p in queryBase.AsEnumerable() // <=== switch to LINQ-to-Objects
            let defaultPoints = p.PersonTypeId == (int)PersonType.Old
                        ? defaultOldPersonPoints
                        : p.PersonTypeId == (int)PersonType.Young
                        ? defaultYoungPersonPoints : 0
            let contractedHourRatio = p.ContractedHours.HasValue 
                        ? (p.ContractedHours.Value - defaultHours) / defaultHours : 0
            select new
            {
                AllocatedPoints = defaultPoints + (int)(defaultPoints * contractedHourRatio)
            });

在这里,SQL查询应该非常简单;所有更复杂的工作都是在LINQ to Objects中完成的。

您实际看过生成的SQL了吗?@SimonWhitehead虽然归根结底都是生成的SQL,但我对不影响生成的SQL的可读性感兴趣是的,但为什么它会影响性能?我们到底在做什么?知道这一点可能会给你一些答案,告诉你如何重构它,让它做同样的事情。。如果没有let,如果确实是let的原因……这个问题似乎是离题的,因为它假设问题与代码有关,而事实上它是环境问题,不再是问题。你真的看过生成的SQL吗?@SimonWhitehead,而这一切归结到生成的SQL,我对不影响生成的SQLYes的可读性感兴趣,但为什么它会影响性能呢?我们到底在做什么?知道这一点可能会给你一些答案,告诉你如何重构它,让它做同样的事情。。没有let如果确实是let的原因…这个问题似乎离题了,因为它假设问题与代码有关,而事实上它是环境问题,不再是问题。回顾这个问题,let版本现在比备用版本执行得更快。。。所以我的问题不再存在了。这可能是当时sql server实例的性能问题。因此,我尝试删除该问题,但由于您的回答,该问题不允许我回答。回顾该问题,let版本现在的执行速度比备用版本快。。。所以我的问题不再存在了。这可能是当时sql server实例的性能问题。因此,我尝试删除该问题,但由于您的回答,该问题不允许删除。