Вопрос

У меня есть запрос 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 варианта:

  1. Вы возвращаете Объект с отслеживанием контекста и все, в данном случае Изображение, со всеми полями
  2. Вы выбираете свои поля и возвращаете анонимный тип
  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 фактически преобразуются в лямбда-выражение во время компиляции, но я предпочитаю использовать выражение запроса в целом, потому что нахожу его более читаемым и понятным.

Спасибо :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top