2009-05-30 19 views
9

Mam kwerendy LINQ odwzorowaną z Entity Framework, który wygląda mniej więcej tak:LINQ - NIE WYBIERANIE niektórych pól?

image = this.Context.ImageSet 
        .Where(n => n.ImageId == imageId) 
        .Where(n => n.Albums.IsPublic == true) 
        .Single(); 

ta zwraca pojedynczy obiekt obrazu i działa zgodnie z przeznaczeniem.

Jednak to zapytanie zwraca wszystkie właściwości mojej tablicy obrazów w bazie danych. W normalnych okolicznościach byłoby to w porządku, ale te obrazy zawierają wiele danych binarnych, których odzyskanie zajmuje bardzo dużo czasu.

Zasadniczo, w tym stan obecny mój zapytań LINQ robi:

Select ImageId, Name, Data 
From Images 
... 

Ale potrzebuję kwerendę, która wykonuje to instread:

Select ImageId, Name 
From Images 
... 

Wskazówka Chcę załadować wszystko oprócz danych. (Mogę uzyskać te dane na drugim asynchronicznym przejściu)

Odpowiedz

8

Niestety, jeśli używasz LINQ do SQL, nie ma optymalnego rozwiązania.

Masz 3 opcje:

  1. wrócisz podmiotu, ze śledzenia kontekstu i wszystko, w tym przypadku obrazu, ze wszystkich dziedzin
  2. skorzystać z pola i zwracają typ anonimowy
  3. Ty wybierz swoje pola i zwróć mocno wpisaną klasę niestandardową, ale tracisz śledzenie, jeśli tego chcesz.

Uwielbiam LINQ do SQL, ale tak to już jest.

Jedyne rozwiązanie dla Ciebie to zrestrukturyzowanie bazy danych i przeniesienie wszystkich dużych danych do oddzielnej tabeli i połączenie z nią w tabeli obrazu.

W ten sposób podczas zwracania obrazu zwrócisz klucz tylko w nowym polu DataID, a następnie będziesz mógł uzyskać dostęp do cięższych danych, gdy zajdzie taka potrzeba.

okrzyki

+0

Myślę, że bez opcji obciążenia opóźnieniem, takich jak LINQ do SQL, jest to najlepsze rozwiązanie dla mnie. – vidalsasoon

+0

Tak, myślę, LINQ do SQL czasami trzeba zmienić swój schemat, aby dopasować model. Czasami okazuje się, że faktycznie kończy się, aby twój projekt DB lepiej ...? – andy

1

Spowoduje to utworzenie nowego obrazu z ustawionymi tylko tymi polami. Po powrocie, aby uzyskać dane dla wybranych zdjęć, sugeruję, aby przejść do pełnego zestawu danych, zamiast próbować scalić go z istniejącymi danymi identyfikatora/nazwy. Pola id/name są prawdopodobnie małe w stosunku do danych, a kod będzie znacznie prostszy niż próba scalenia. Ponadto może nie być konieczne faktyczne skonstruowanie obiektu Image, przy użyciu anonimowego typu może również pasować do własnych celów.

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(); 
+1

Myślałem o rozwiązaniu, które podałeś, ale moim zmartwieniem była utrata stanu obiektu, ponieważ tworzony jest nowy obraz. Ponadto typem zwracanym jest "Obraz", więc nie wydaje mi się, aby był możliwy typ anonimowy. Zrobię kilka testów thx – vidalsasoon

0

Alternatywnie można użyć select nowego w wyrażeniu kwerendy ...

var image = 
(
    from i in db.ImageSet 
    where i.ImageId == imageId && i.Albums.IsPublic 
    select new 
    { 
     ImageId = i.ImageId, 
     Name = i.Name 
    } 
).Single() 

Wyrażenia zapytań LINQ faktycznie przekonwertowane do wyrażenia lambda w czasie kompilacji, ale PreFair używając wyrażenia kwerendy ogólnie, ponieważ uważam, że jest bardziej czytelny i zrozumiały.

Dzięki :)

1

[Jeżeli przy użyciu LINQ 2 SQL] W projektancie dbml, istnieje możliwość, aby jednostka kolumny tabeli opóźnić załadowane. Ustaw to na true dla twojego dużego pola binarnego. Następnie dane te nie zostaną załadowane, dopóki nie zostaną faktycznie użyte.

[Pytanie dla was wszystkich: Czy ktoś wie, czy struktury encji obsługują opóźnione załadowane varbinary/varchar w MSVS 2010? ]

Rozwiązanie nr 2 (dla Entity Framework lub LINQ 2 SQL):

utworzyć widok tabeli, która zawiera tylko klucz podstawowy i varchar (max)/varbinary (max). Zamapuj to na EF.

W projekcie Entity Framework usuń właściwość varbinary (max)/varchar (max) z definicji tabeli (pozostawiając ją zdefiniowaną tylko w widoku). To powinno wykluczać pole z operacji odczytu/zapisu do tej tabeli, ale możesz to sprawdzić za pomocą rejestratora.

Zasadniczo uzyskasz dostęp do danych za pomocą tabeli, która nie obejmuje danych blob. Kiedy potrzebujesz kropelki, ładujesz wiersz z widoku. Nie jestem pewien, czy będziesz w stanie napisać do widoku, nie jestem pewien, jak byś napisał. Możesz być w stanie napisać do widoku lub możesz napisać procedurę przechowywaną, lub możesz zniszczyć plik DBML dla jednej tabeli.

+0

Myślę, że to jest tylko dla LINQ do SQL? Szkoda. byłby idealny – vidalsasoon

+0

Ups, tak, to może być tylko linq 2 sql. –

+0

[Pytanie dla was wszystkich: Czy ktoś wie, czy struktury encji obsługują opóźnione załadowane varbinary/varchar w MSVS 2010? ] ODPOWIEDŹ: NIE :( – vidalsasoon

1

Nie można zrobić z LINQ przynajmniej na razie ...

najlepszym rozwiązaniem jest stworzenie wiem View na stole trzeba bez dużych pól i wykorzystać LINQ z to View.

+1

tak to jest tylko sposób! Próbowałem wybrać niektóre pola z niestandardowej klasy, ale problem pozostaje nvarchar pola (max) z xmlFile nie jest w wybierz, ale awarię z Błąd podczas wykonywania żądania podrzędnego dla obsługi 'System.Web.Mvc.HttpHandlerUtil + ServerExecuteHttpHandlerAsyncWrapper'. Użyłem widoku bez dużych plików i działa! – Evilripper

Powiązane problemy