LINQ select query с анонимным типом и пользовательским типом
анонимный класс имеет свойства только для чтения в 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();
если я не упомянул тип после new
на select
заявление я не могу покинуть. компилятор поднять ошибка. enonymous объект только для чтения.
var query = (from entity in _tblStudentClerkshipsLog.GetQueryable()
where entity.StudentID == intStudentID
select new
{
StudentClerkshipID = entity.StudentClerkshipID,
StudentID = entity.StudentID,
ClerkshipID = entity.ClerkshipID,
}).ToList()
мой вопрос в том, как linq связывает два запроса по-разному . Оба запроса имеют динамическую привязку или первый является статическим.
спасибо
3 ответов
если я правильно вас понимаю, вам интересно, как поставщик 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);
}
}
разница в том, как компилятор генерирует лямбда-выражения для именованных и анонимных типов. Когда вы звоните Select
для именованного типа, выражение будет выглядеть так:
{_ => new Person() {Id = _.Id, Name = _.Name}}
то есть, во-первых новый Person
объект будет построен, а затем члены будут инициализированы (MemberInit
выражение).
но когда вы называете Select
для анонимного типа выражение будет построено как вызов конструктора (New
выражения):
{_ => new <>f__AnonymousType0`2(a = _.Id, b = _.Name)}
поставщик 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.
результат не редактируется, например, если мы назначаем значение gridview будет только чтение.
проблема с областью неизвестного объекта.мы не можем пройти тип к другому методу. определите параметр типа var; var должен всегда затем следует выражение инициализации.
Если вам нужен результат только в текущем контекст только для чтения используйте анонимный запрос . Если вам нужен результат в другой функции, вы должны определить тип объекта. тип объекта после new
будет создан со свойствами, которые вы хотите получить в результате определения затем в фигурных скобках {}
.
Нет необходимости инициализировать все значения класса model.