3

抱歉标题不好......这可能最好用一个例子来解释:

void Main()
{
    IQueryable<ClassA> toLinkTo = context.ClassAs.Where(a => a.Name == "SomeName");

    var queryToExecute = context.ClassBs.Where(cb => toLinkTo.Select(ca => ca.Id).Contains(cb.Id));

    // This works.
    leafNodesWithExternalChildren.ToList();

    // This doesn't work.
    toLinkTo = new OtherClass(context).LinkedClassAs;
    leafNodesWithExternalChildren.ToList();
}

public class OtherClass
{
    private MyContext m_Context;

    public OtherClass(MyContext ctx)
    {
        this.m_Context = ctx;
    }

    public IQueryable<ClassA> LinkedClassAs
    {
        get
        {
            // Same as toLinkTo as it was originally declared above.
            return this.m_Context.ClassAs.Where(a => a.Name == "SomeName");
        }
    }
}

当在本地声明时如何工作toLinkTo,但使用与另一个对象上的属性完全相同IQueryable的属性却没有?我得到的例外是:

Unable to create a constant value of type 'ClassA'. Only primitive types ('such as Int32, String, and Guid') are supported.

提前致谢。

4

1 回答 1

3

您的第二个示例也有效 - 如果您将其作为第一个示例:

IQueryable<ClassA> toLinkTo = new OtherClass(context).LinkedClassAs;
var queryToExecute = context.ClassBs.Where(cb => toLinkTo.Select(ca => ca.Id)
                                                         .Contains(cb.Id));

// Now, this works.
queryToExecute.ToList();

// Now, this doesn't work.
toLinkTo = context.ClassAs.Where(a => a.Name == "SomeName");
queryToExecute.ToList();

Somwhow,在第二次尝试中,EFtoLinkTo预先单独执行查询(好像它会将一个附加AsEnumerable()到查询中)以首先在内存中创建对象集合。queryToExecute不适用于此集合-如@mellamokb 的回答中所述。在第一次尝试中,查询是作为一个整体执行的,并且不会出现问题。

如果您queryToExecute2为第二个示例创建一个新变量,这两个示例都有效:

IQueryable<ClassA> toLinkTo = context.ClassAs.Where(a => a.Name == "SomeName");
var queryToExecute = context.ClassBs.Where(cb => toLinkTo.Select(ca => ca.Id)
                                                         .Contains(cb.Id));

// this works.
queryToExecute.ToList();

// And this works too.
toLinkTo = new OtherClass(context).LinkedClassAs;
var queryToExecute2 = context.ClassBs.Where(cb => toLinkTo.Select(ca => ca.Id)
                                                          .Contains(cb.Id));
queryToExecute2.ToList();

它可能与表达式树的queryToExecute构建方式以及它如何使用局部变量toLinkTo或 EF 如何评估树的方式有关,但我无法真正理解或解释到底发生了什么。

编辑

即使您toLinkTo在第二次尝试中使用完全相同的查询也不起作用:

IQueryable<ClassA> toLinkTo = context.ClassAs.Where(a => a.Name == "SomeName");
var queryToExecute = context.ClassBs.Where(cb => toLinkTo.Select(ca => ca.Id)
                                                         .Contains(cb.Id));

// this works.
queryToExecute.ToList();

// this doesn't work.
toLinkTo = context.ClassAs.Where(a => a.Name == "SomeName");
queryToExecute.ToList();
于 2012-04-04T16:03:41.800 回答