ฉันจะแคชแบบสอบถาม LINQ ที่คอมไพล์แล้ว (ไม่ใช่ผลลัพธ์) ได้อย่างไร

ดูเหมือนว่าทุกครั้งที่ฉันสืบค้นบางสิ่งด้วย LINQ NHibernate บิลด์การสืบค้นนั้นตั้งแต่เริ่มต้น:

รายงาน dotTrace

รหัสดูเหมือนว่า

session.Query<User>().Where(x => ids.Contains(x.Id)).ToFuture();

เป็นไปได้ไหมที่จะหลีกเลี่ยงการคอมไพล์ใหม่?

คำถามเดียวกันเกี่ยวกับการแคชแบบสอบถาม QueryOver/Criteria (ไม่สำคัญนัก แต่อาจยังพอดีกับขอบเขต)


person Vlad    schedule 07.08.2017    source แหล่งที่มา
comment
@stybl การใช้แบบสอบถาม LINQ ซ้ำและการใช้ LINQ ซ้ำกับฐานข้อมูลแบบสอบถาม NH นั้นไม่เหมือนกัน   -  person Vlad    schedule 08.08.2017
comment
ฉันทราบแล้ว ซึ่งเป็นสาเหตุที่ฉันถอนการลงคะแนนเสียงปิด แต่ลืมความเห็นไป   -  person stybl    schedule 08.08.2017
comment
stackoverflow.com/a/4817010/1162077   -  person David Osborne    schedule 08.08.2017


คำตอบ (2)


ฉันจำได้ว่านิพจน์ที่มีเมธอด linq จะไม่ถูกรวบรวมเนื่องจากการแจงนับอาจแตกต่างกันในการโทรในอนาคต

วิธีแก้ปัญหาที่เป็นไปได้คือการใช้ตัวดำเนินการ OR ในลักษณะที่น่าเกลียด หากคุณรู้ว่าจำนวนองค์ประกอบจะเท่ากันเสมอ

วิธีแก้ปัญหาอื่นคือการเรียกวิธีการต่อไปนี้:

session.QueryOver().AndRestrictionOn(x=>x.id).IsIn(รหัส)

person Molem    schedule 14.06.2020

โดยเฉพาะกรณีนี้เกิดจากการที่เข้าถึงรหัส (int[]) ที่นี่

session.Query<User>().Where(x => ids.Contains(x.Id)).ToFuture();

ถูกแปลงเป็น MemberAccessExpression (ไม่ใช่ ConstantExpression) และ NHibernate ต้องประเมินผล แม้ว่า ids จะไม่ถูกเปลี่ยนแปลง แต่ก็ยังถูกบันทึกลงในคลาสที่สร้างการปิด (เช่น DisplayClass<>.ids)

ฉันปรับปรุงกรณีนี้ให้เหมาะสมโดยสร้าง PartialEvaluatingExpressionTreeVisitor เวอร์ชันของตัวเอง:

    protected Expression EvaluateSubtree(Expression subtree)
    {
        ArgumentUtility.CheckNotNull(nameof(subtree), subtree);
        var memberExpression = subtree as MemberExpression;
        if (memberExpression != null)
        {
            Expression constant;
            if (TryEvaluateMember(memberExpression, out constant)) return constant;
        }

        if (subtree.NodeType != ExpressionType.Constant)
            throw new NHibernateExpressionOptimizerException(subtree);
        ConstantExpression constantExpression = (ConstantExpression)subtree;
        IQueryable queryable = constantExpression.Value as IQueryable;
        if (queryable != null && queryable.Expression != constantExpression)
            return queryable.Expression;
        return constantExpression;
    }

    bool TryEvaluateMember(MemberExpression memberExpression, out Expression constant)
    {
        constant = null;
        ConstantExpression c = memberExpression.Expression == null ? Expression.Constant(null) : EvaluateSubtree(memberExpression.Expression) as ConstantExpression;
        if (c == null) return false;
        var fieldInfo = memberExpression.Member as FieldInfo;
        if (fieldInfo != null)
        {
            constant = Expression.Constant(ReflectorReadFieldDelegate(fieldInfo, c.Value));
            return true;
        }

        var propertyInfo = memberExpression.Member as PropertyInfo;
        if (propertyInfo != null)
        {
            constant = Expression.Constant(ReflectorReadPropertyDelegate(propertyInfo, c.Value));
            return true;
        }
        return false;
    }

ผู้ร่วมประชุมตัวสะท้อนแสงใช้เวทย์มนตร์การสะท้อนที่แคชไว้

person Vlad    schedule 08.08.2017
comment
ฟังดูเหมือนการเปลี่ยนพฤติกรรมเริ่มต้น ซึ่งโดยทั่วไปแล้วฉันไม่ชอบเลย ทำไมไม่รวมมันไว้ด้วยการเรียกเมธอด เช่น public static T ToConst‹T›(T item) { return item;} แล้วใช้ตรรกะของคุณสำหรับการเรียกเมธอดนั้นล่ะ? มันทำให้คุณมีความยืดหยุ่นมากขึ้น และชัดเจนมากขึ้นว่าคุณมีเจตนาอะไร? - person MBoros; 12.08.2017