Z kilku powodów, o których nie mogę mówić, definiujemy widok naszej bazy danych Sql Server 2005 w następujący sposób:
CREATE VIEW [dbo].[MeterProvingStatisticsPoint]
AS
SELECT
CAST(0 AS BIGINT) AS 'RowNumber',
CAST(0 AS BIGINT) AS 'ProverTicketId',
CAST(0 AS INT) AS 'ReportNumber',
GETDATE() AS 'CompletedDateTime',
CAST(1.1 AS float) AS 'MeterFactor',
CAST(1.1 AS float) AS 'Density',
CAST(1.1 AS float) AS 'FlowRate',
CAST(1.1 AS float) AS 'Average',
CAST(1.1 AS float) AS 'StandardDeviation',
CAST(1.1 AS float) AS 'MeanPlus2XStandardDeviation',
CAST(1.1 AS float) AS 'MeanMinus2XStandardDeviation'
WHERE 0 = 1
Chodzi o to, że Entity Framework utworzy jednostkę na podstawie tego zapytania, co robi, ale generuje ją z błędem, który stwierdza, co następuje:
Ostrzeżenie 6002: Tabela / widok „Keystone_Local.dbo.MeterProvingStatisticsPoint” nie ma zdefiniowanego klucza podstawowego. Klucz został wywnioskowany, a definicja została utworzona jako tabela / widok tylko do odczytu.
I decyduje, że pole CompletedDateTime będzie kluczem podstawowym tej jednostki.
Używamy EdmGen do generowania modelu. Czy istnieje sposób, aby struktura encji nie zawierała żadnego pola tego widoku jako klucza podstawowego?
źródło
Udało mi się to rozwiązać za pomocą projektanta.
Nie musiałem zmieniać widoku, aby użyć obejść ISNULL, NULLIF lub COALESCE. Jeśli zaktualizujesz model z bazy danych, ostrzeżenia pojawią się ponownie, ale znikną, jeśli zamkniesz i ponownie otworzysz VS. Zmiany wprowadzone w projektancie zostaną zachowane i odświeżenie nie będzie miało na nie wpływu.
źródło
Zgadzam się z @Tillito, jednak w większości przypadków będzie to zakłócać optymalizator SQL i nie będzie używał właściwych indeksów.
Może to być dla kogoś oczywiste, ale spędziłem godziny na rozwiązywaniu problemów z wydajnością za pomocą rozwiązania Tillito. Powiedzmy, że masz stół:
a twój pogląd jest mniej więcej taki
Sql Optimizer nie użyje indeksu ix_customer i wykona skanowanie tabeli na indeksie podstawowym, ale jeśli zamiast:
używasz
sprawi, że MS SQL (przynajmniej 2008) włączy odpowiedni indeks do planu.
Jeśli
źródło
Ta metoda działa dobrze dla mnie. Używam ISNULL () dla pola klucza podstawowego i COALESCE (), jeśli pole nie powinno być kluczem podstawowym, ale powinno również mieć wartość nie dopuszczającą wartości null. Ten przykład daje pole identyfikatora z kluczem podstawowym niepodlegającym wartości null. Pozostałe pola nie są kluczami i mają atrybut (Brak) jako atrybut dopuszczający wartość zerową.
jeśli naprawdę nie masz klucza podstawowego, możesz go sfałszować, używając ROW_NUMBER do wygenerowania pseudoklucza, który jest ignorowany przez Twój kod. Na przykład:
źródło
NEWID() as id
, ale to ten sam pomysł. Są też uzasadnione przypadki użycia - na przykład jeśli masz widok tylko do odczytu. Brzydki, EF, brzydki.Bieżący generator Entity Framework EDM utworzy klucz złożony ze wszystkich pól niepodlegających wartości null w Twoim widoku. Aby uzyskać kontrolę nad tym, musisz zmodyfikować widok i kolumny tabeli bazowej, ustawiając kolumny na wartości null, jeśli nie chcesz, aby były częścią klucza podstawowego. Odwrotna prawda jest również prawdą, ponieważ napotkałem, że wygenerowany klucz EDM powodował problemy z duplikacją danych, więc musiałem zdefiniować kolumnę dopuszczającą wartość null jako nieprzekraczającą wartości null, aby zmusić klucz złożony w EDM do uwzględnienia tej kolumny.
źródło
Context.Entity.ToList()
zduplikowane rekordy, ale jeśli wykonasz zapytanie SQL wygenerowane przez EF bezpośrednio (uzyskane za pomocą LINQPad), nie nastąpi duplikacja rekordów. Wydaje się, że występuje problem z mapowaniem rekordów bazy danych na zwrócone obiekty jednostki (POCO), ponieważ PK jest wywnioskowana przy użyciu wyjaśnionej logiki (kolumny bez wartości null).Wygląda na to, że jest to znany problem z EdmGen: http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/12aaac4d-2be8-44f3-9448-d7c659585945/
źródło
Aby uzyskać widok, musiałem pokazać tylko jeden kolumnę klucza podstawowego, utworzyłem drugi widok, który wskazywał na pierwszy i użyłem NULLIF, aby nadać typom wartość null. Pomogło mi to, aby EF pomyślał, że w widoku jest tylko jeden klucz podstawowy.
Nie jestem pewien, czy to ci pomoże, ponieważ nie wierzę, że EF zaakceptuje jednostkę bez klucza podstawowego.
źródło
Jeśli nie chcesz bawić się kluczem podstawowym, polecam:
ROW_NUMBER
do swojego wyboruźródło
Ze względu na powyższe problemy preferuję funkcje tabelaryczne.
Jeśli masz to:
utwórz to:
Następnie po prostu importujesz funkcję, a nie widok.
źródło