如何使用LINQ to Entities初始化匿名类型?

时间:2018-01-24 09:11:03

标签: c# entity-framework linq

LINQ to entities支持匿名类型作为返回类型,例如:

class TeacherSignupView(View):
    def get_context_data(self):
        return {'user_form': self.user_form_class, 'teacher_form': self.teacher_form_class}

    def get(self, request, *args, **kwargs):
        return render(request, 'form.html', self.get_context_data())

    def post(self, request, *args, **kwargs):
        user_data = {
           'some-user-field': request.POST.get('some-user-field')
        }
        teacher_data = {
           'some-teacher-field': request.POST.get('some-teacher-field')
        }

        # Handle each set of form data individually
        user_form = self.user_form_class(user_data)

        # Check valid
        if user_form.is_valid():
            user = user_form.save()
            # If user form is valid and user data is saved, then proceed with teacher data
            teacher_data["user"] = user  # add the user relation here
            teacher_form = self.teacher_form_class(teacher_data)
            if teacher_form.is_valid():
                teacher_form.save()

        return render_to_response('index.html', self.get_context_data())

和编译器生成的代码类似于:

var query = from a in b.C select new { Value = a.Value };

但是如果我使用生成的匿名类型实例:

private class f__AnonymousType0<j__TPar>
{
    private readonly j__TPar i__Field;
    public j__TPar Value
    {
        get { return i__Field; }
    }

    public f__AnonymousType0(j__TPar Value)
    {
        i__Field = Value;
    }
}

错误:

var query = from a in b.C select new f__AnonymousType0<string>(a.Value);

将被抛出。

那么匿名类型如何在这里工作?

1 个答案:

答案 0 :(得分:5)

如果编译器必须执行一个匿名类型的初始化器,那么它最终会调用构造函数。但是在LINQ to Entities - 或任何其他基于IQueryable的LINQ提供程序中 - 代码实际上并未执行......它只是转换为表达式树。

所以在你的样本中:

var query = from a in b.C select new { Value = a.Value };

...将转换为对Expression.New的调用,它有效地表示匿名类型初始值设定项。至关重要(我相信),它会创建一个NewExpression,并设置Members属性,以指示Value属性已从构造函数的第一个参数初始化。

我希望LINQ to Entities分析NewExpression以找出原始代码的含义,并推断将其转换为SQL需要做什么。它只能通过构造函数调用来实现。