LINQ - НЕ выбираются определенные поля?
-
06-09-2019 - |
Вопрос
У меня есть запрос LINQ, сопоставленный с Entity Framework, который выглядит примерно так:
image = this.Context.ImageSet
.Where(n => n.ImageId == imageId)
.Where(n => n.Albums.IsPublic == true)
.Single();
Это возвращает один объект изображения и работает по назначению.
Однако этот запрос возвращает все свойства моей таблицы изображений в базе данных.При обычных обстоятельствах это было бы прекрасно, но эти изображения содержат много двоичных данных, возврат которых занимает очень много времени.
По сути, в текущем состоянии мой запрос linq выполняет:
Select ImageId, Name, Data
From Images
...
Но мне нужен запрос, который выполняет это instread:
Select ImageId, Name
From Images
...
Обратите внимание, что я хочу загрузить все, кроме Данных.(Я могу получить эти данные при втором асинхронном проходе)
Решение
К сожалению, при использовании LINQ to SQL оптимального решения не существует.
У вас есть 3 варианта:
- Вы возвращаете Объект с отслеживанием контекста и все, в данном случае Изображение, со всеми полями
- Вы выбираете свои поля и возвращаете анонимный тип
- Вы выбираете свои поля и возвращаете строго типизированный пользовательский класс, но вы теряете отслеживание, если это то, что вы хотите.
Мне нравится LINQ to SQL, но так оно и есть.
Моим единственным решением для вас было бы реструктурировать вашу базу данных и переместить все большие данные в отдельную таблицу и создать ссылку на нее из таблицы изображений.
Таким образом, при возврате изображения вы бы возвращали только ключ в поле new DataID, и тогда вы могли бы получить доступ к этим более тяжелым данным, когда и если бы вам это было нужно.
ваше здоровье
Другие советы
Это создаст новое изображение, в котором будут заданы только эти поля.Когда вы вернетесь, чтобы получить данные для выбранных вами изображений, я бы посоветовал продолжить и получить полный набор данных вместо того, чтобы пытаться объединить его с существующими данными id / name.Поля id / name, по-видимому, невелики по сравнению с данными, и код будет намного проще, чем пытаться выполнить слияние.Кроме того, возможно, нет необходимости создавать объект Image на самом деле, использование анонимного типа может также подходить для ваших целей.
image = this.Context.ImageSet
.Where(n => n.ImageId == imageId)
.Where(n => n.Albums.IsPublic == true)
.Select( n => new Image { ImageId = n.ImageId, Name = n.Name }
.Single();
[При использовании Linq 2 SQL] В конструкторе DBML есть возможность сделать так, чтобы отдельные столбцы таблицы загружались с задержкой.Установите для этого значения значение true для вашего большого двоичного поля.Затем эти данные не загружаются до тех пор, пока они фактически не будут использованы.
[Вопрос ко всем вам:Кто-нибудь знает, поддерживают ли entity framework задержку загрузки varbinary / varchar в MSVS 2010?]
Решение № 2 (для entity Framework или linq 2 sql):
Создайте представление таблицы, которое включает только первичный ключ и varchar(max) / varbinary(max).Сопоставьте это с EF.
В вашем конструкторе Entity Framework удалите свойство varbinary(max) / varchar(max) из определения таблицы (оставив его определенным только в представлении).Это должно исключить поле из операций чтения / записи в эту таблицу, хотя вы можете проверить это с помощью регистратора.
Как правило, вы получаете доступ к данным через таблицу, которая исключает большой двоичный объект данных.Когда вам нужен большой двоичный объект, вы загружаете строку из представления.Я не уверен, сможете ли вы писать в представление, я не уверен, как бы вы делали записи.Возможно, вы сможете выполнять запись в представление, или вам может понадобиться написать хранимую процедуру, или вы можете создать файл DBML для одной таблицы.
Вы не можете сделать это с помощью LINQ по крайней мере, на данный момент...
Лучший подход, который я знаю, - это создавать View
для нужной вам таблицы без больших полей и использования LINQ с этим View
.
В качестве альтернативы вы могли бы использовать команду select new в выражении запроса...
var image =
(
from i in db.ImageSet
where i.ImageId == imageId && i.Albums.IsPublic
select new
{
ImageId = i.ImageId,
Name = i.Name
}
).Single()
Выражения запроса LINQ фактически преобразуются в лямбда-выражение во время компиляции, но я предпочитаю использовать выражение запроса в целом, потому что нахожу его более читаемым и понятным.
Спасибо :)