繁体   English   中英

LINQ选择具有匿名类型和用户定义类型的查询

[英]LINQ select query with Anonymous type and user Defined type

匿名类在c#中只读取属性。 这通常用于在linq select query中声明从数据库中获取特定值。 在我的代码中,我有以下查询。让我混淆使用新语句选择匿名类的新对象的事情。 我有一个StudentClerkshipsLogModel的模型类。 当我使用模型名称时,查询结果允许编辑。

var query = (from entity in _tblStudentClerkshipsLog.GetQueryable()
             where entity.StudentID == intStudentID                             
             select new StudentClerkshipsLogModel
             {
                 StudentClerkshipID = entity.StudentClerkshipID,
                 StudentID = entity.StudentID,
                 ClerkshipID = entity.ClerkshipID,
             }).ToList();

当我在select语句中没有提到new之后的类型时,我无法退出。 编译器引发错误。 匿名对象是只读的。

var query = (from entity in _tblStudentClerkshipsLog.GetQueryable()
             where entity.StudentID == intStudentID                             
             select new 
             {
                 StudentClerkshipID = entity.StudentClerkshipID,
                 StudentID = entity.StudentID,
                 ClerkshipID = entity.ClerkshipID,
             }).ToList()

我的问题是linq如何以不同方式绑定两个查询。 两个查询都有动态绑定,或者第一个是静态的。

谢谢

你得到的错误与LINQ没有任何关系。 你可以在不使用LINQ的情况下看到同样的事情:

var anonymous = new { Name = "Fred" };
anonymous.Name = "Joe"; // Error, as properties of anonymous types are read-only

因此,如果要修改LINQ查询提取的对象,则不应使用匿名类型。 但是两个LINQ查询都是静态绑定的 - 匿名类型在编译时仍然是完全已知的,并且编译器对它们应用常规类型限制。 例如:

var anonymous = new { Name = "Fred" };
Console.WriteLine(anonymous.Foo); // Error: no property Foo
int bar = anonymous.Name; // Error: no conversion from string to int

如果我理解正确,你会想知道,LINQ提供程序如何设置匿名对象的属性,因为它们是“真正的”只读属性(没有任何private set ,但只有get )?

当你调用Select用于扩展方法IQueryable<T>它接受类型的表达式 Expression<Func<T, TResult> 如果您要为Select编写一些存根,可以使用调试器查看生成的表达式:

public static class MyExtensions
{
    public static void MySelect<T, TResult>(this IQueryable<T> query, Expression<Func<T, TResult>> projection)
    {
        System.Diagnostics.Debug.WriteLine(projection);
    }
}

不同之处在于编译器如何为命名类型和匿名类型生成lambda表达式。 当您为名称类型调用Select ,表达式将如下所示:

{_ => new Person() {Id = _.Id, Name = _.Name}}

也就是说,首先将构造新的Person对象,然后初始化成员( MemberInit表达式)。

但是当您为匿名类型调用Select时,表达式将构建为构造函数调用( New expression):

{_ => new <>f__AnonymousType0`2(a = _.Id, b = _.Name)}

LINQ提供程序在实现查询结果时将这些lambda编译为委托,最终只调用匿名类型的构造函数。

我发现LINQ结果的匿名类型结果存在以下差异。

  1. 结果不能编辑,例如,如果我们将值分配给gridview,它将是只读的。

  2. 匿名对象的范围问题。我们无法将类型传递给另一个方法。 定义var类型的参数; var必须始终后跟初始化表达式。

如果仅在当前上下文中需要结果以用于只读目的,请使用匿名查询。 如果您需要在其他函数中生成结果,则必须定义对象的类型。 new之后的对象类型将使用您希望从结果定义获得的属性创建,然后在花括号{} 没有必要初始化模型类的所有值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM