Entity Framework i widok SQL Server

Z kilku powodów, o których nie mam wolności mówić, definiujemy widok na naszej bazie 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

Idea jest taka, że struktura encji utworzy encję na podstawie tego zapytania, co robi, ale generuje ją z błędem, który stwierdza, co następuje:

Warning 6002: the table / view ' Keystone_Local.dbo.MeterProvingStatisticsPoint " nie ma zdefiniowanego klucza podstawowego. Klucz został wywnioskowany, a definicja była utworzony jako tabela / widok Tylko do odczytu.

I decyduje, że pole CompletedDateTime będzie głównym kluczem tej jednostki.

Używamy EdmGen do generowania modelu. Czy istnieje sposób, aby Framework entity nie zawierał żadnego pola tego widoku jako klucza podstawowego?

Author: abatishchev, 2009-06-18

9 answers

Mieliśmy ten sam problem i jest to rozwiązanie:

Aby wymusić użycie kolumny jako klucza podstawowego, użyj ISNULL.

Aby wymusić, aby struktura encji nie używała kolumny jako klucza podstawowego, użyj NULLIF.

Łatwym sposobem zastosowania tego polecenia jest zawinięcie instrukcji select w widoku w inne polecenie select.

Przykład:

SELECT
  ISNULL(MyPrimaryID,-999) MyPrimaryID,
  NULLIF(AnotherProperty,'') AnotherProperty
  FROM ( ... ) AS temp
 231
Author: Tillito,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-26 17:00:42

Udało mi się to rozwiązać za pomocą projektanta.

  1. Otwórz przeglądarkę modelu.
  2. Znajdź widok na diagramie.
  3. Kliknij prawym przyciskiem myszy klucz główny i upewnij się, że jest zaznaczona opcja "Encja klucz".
  4. wielokrotne wybieranie wszystkich klawiszy innych niż podstawowe. Użyj klawiszy Ctrl lub Shift.
  5. w oknie Właściwości (wciśnij F4, jeśli chcesz go zobaczyć), Zmień "Klucz encji" rozwijany do False.
  6. Zapisz zmiany.
  7. Zamknij Visual Studio i otwórz je ponownie. Korzystam z Visual Studio 2013 z EF 6 musiałem to zrobić, żeby przestrogi zniknęły.

Nie musiałem zmieniać poglądu, aby korzystać z 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 nie będą miały wpływu na odświeżenie.

 61
Author: Casey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-18 19:04:28

Zgadzam się z @Tillito, jednak w większości przypadków będzie to faul SQL optimizer i nie będzie używał właściwych indeksów.

To może być oczywiste dla kogoś, ale spaliłem godziny rozwiązując problemy z wydajnością za pomocą rozwiązania Tillito. Powiedzmy, że masz tabelę:

 Create table OrderDetail
    (  
       Id int primary key,
       CustomerId int references Customer(Id),
       Amount decimal default(0)
    );
 Create index ix_customer on OrderDetail(CustomerId);

A twój widok jest coś takiego

 Create view CustomerView
    As
      Select 
          IsNull(CustomerId, -1) as CustomerId, -- forcing EF to use it as key
          Sum(Amount) as Amount
      From OrderDetail
      Group by CustomerId

SQL optimizer nie użyje index ix_customer i wykona skanowanie tabeli na indeksie głównym, ale jeśli zamiast:

Group by CustomerId

Używasz

Group by IsNull(CustomerId, -1)

Sprawi, że MS SQL (co najmniej 2008) dołączają odpowiedni Indeks do planu.

If

 45
Author: Val Bakhtin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-10 17:57:53

Ta metoda działa dobrze dla mnie. Używam ISNULL () dla pola klucza podstawowego i COALESCE (), jeśli pole nie powinno być kluczem głównym, ale powinno mieć również wartość nie-nullable. W tym przykładzie otrzymuje się pole ID z nieujemnym kluczem podstawowym. Pozostałe pola nie są kluczami i mają (None) jako atrybut Nullable.

SELECT      
ISNULL(P.ID, - 1) AS ID,  
COALESCE (P.PurchaseAgent, U.[User Nickname]) AS PurchaseAgent,  
COALESCE (P.PurchaseAuthority, 0) AS PurchaseAuthority,  
COALESCE (P.AgencyCode, '') AS AgencyCode,  
COALESCE (P.UserID, U.ID) AS UserID,  
COALESCE (P.AssignPOs, 'false') AS AssignPOs,  
COALESCE (P.AuthString, '') AS AuthString,  
COALESCE (P.AssignVendors, 'false') AS AssignVendors 
FROM Users AS U  
INNER JOIN Users AS AU ON U.Login = AU.UserName  
LEFT OUTER JOIN PurchaseAgents AS P ON U.ID = P.UserID

Jeśli naprawdę nie masz klucza podstawowego, możesz go sfałszować, używając ROW_NUMBER do wygenerowania pseudo-klucza, który jest ignorowany przez Twój kod. Na przykład:

SELECT
ROW_NUMBER() OVER(ORDER BY A,B) AS Id,
A, B
FROM SOMETABLE
 8
Author: SpazDude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-29 23:07:46

Generator EDM current Entity Framework utworzy klucz złożony ze wszystkich pól nieujemnych w widoku. Aby uzyskać kontrolę nad tym, musisz zmodyfikować widok i kolumny tabeli, ustawiając kolumny na nullable, jeśli nie chcesz, aby były częścią klucza podstawowego. Odwrotnie jest również prawdą, jak napotkałem, EDM wygenerowany klucz powodował problemy z duplikacją danych, więc musiałem zdefiniować kolumnę nullable jako non-nullable, aby wymusić klucz kompozytowy w EDM, aby włączyć tę kolumnę.

 4
Author: Annagram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-07 18:54:56
 3
Author: RBarryYoung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-18 15:55:19

Aby uzyskać widok musiałem pokazać tylko jedną kolumnę klucza podstawowego stworzyłem drugi widok, który wskazywał na pierwszy i użyłem NULLIF, aby typy były nullable. To zadziałało dla mnie, aby EF myślał, że jest tylko jeden klucz podstawowy w widoku.

Nie jestem pewien, czy to ci pomoże, ponieważ nie wierzę, że EF zaakceptuje byt bez klucza głównego.

 3
Author: Nick Gotch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 23:02:49

Polecam również, jeśli nie chcesz mieszać z tym, co powinno być kluczem głównym, aby włączyć numer ROW_NUMBER do zaznaczenia i ustawić go jako klucz podstawowy i ustawić wszystkie inne kolumny / memebery jako nie-podstawowe w modelu.

 2
Author: Santhos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-25 13:22:19

Ze względu na wyżej wymienione problemy preferuję funkcje wartości tabeli.

Jeśli masz to:

CREATE VIEW [dbo].[MyView] AS SELECT A, B FROM dbo.Something

Utwórz to:

CREATE FUNCTION MyFunction() RETURNS TABLE AS RETURN (SELECT * FROM [dbo].[MyView])

Następnie po prostu importujesz funkcję, a nie Widok.

 1
Author: Ray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-03 20:14:51