Pytanie SQL: Określona obsada jest niepoprawna


Uwaga: Szukam, dlaczego tak się dzieje i jak to naprawić, nie szukam obejścia. Wygląda na to, że jest to serwer (SQL Server lub ciąg połączenia).

Mam program, który jest podłączony do bazy danych sql 2008 (Baza danych A) i mam wbudowany sql, który działa, który ma zwracane ints i łańcuchy i działa dobrze. Ale zostałem poproszony o przejście do innej bazy danych 2008 (Baza B), a teraz wszystko wraca jako ciąg i otrzymuję określony rzut nie jest poprawny z C #, gdzie kiedy jestem podłączony do sql 2008 (Baza danych A) to nie mówi tego. Jest to wbudowane wyrażenie sql, więc instrukcja SQL nie zmienia się, a schemat tabeli bazy danych jest taki sam. Robi to na int podstawowych kluczy Ktoś ma jakieś pomysły?

Początkowo myślałem, że to problem z lat 2000-2008, ale teraz mam też problem w 2008 roku. Obie bazy danych znajdują się na tym samym wystąpieniu serwera sql, są to ciągi połączenia

Ciągi połączeń

  Server=Server01\instance;Database=Fraud_Micah; Trusted_Connection=yes <- Server 2008 (this one does not)
  Server=Server02\instance;Database=Fraud; Trusted_Connection=yes <- Server 2008 (this one works)

Obie bazy danych są na poziomie kompatybilności DB 100

Wybierz instrukcję

select *, delimeter, file_filetype.LocalPath, ArchiveDir, EmailList
from file_importtable 
join file_filetype on file_importtable.FileTypeID = file_filetype.ID
where importsuccessdate is null and transferdate is not null
and remotediscoverdate is not null 
and OriginalFileName in ('Test987.xml.pgp')

fileTypeID gdzie jest jego zerwanie -> InvalidCastException: Specified cast is not valid.

Kod C # (czytnik nut jest typu SQLDataReader)

if (!(reader.IsDBNull(reader.GetOrdinal("FileTypeID"))))
{
    file.FileTypeID = reader.GetInt32(reader.GetOrdinal("FileTypeID"));
}

Oto definicja kolumny: [FileTypeID] [int] NULL, nie ma pustych wartości w tabeli.

Nie sądzę, kod C # pochodzi z tego, jego int? public int? FileTypeID { get; set; }

W trybie debugowania: reader["FileTypeID"] -> "1" to w rzeczywistości ciąg znaków, ale dlaczego po połączeniu się z bazą danych z 2008 r. Zwróci 1 instaed "1"

2008 Tabela A Def

[ProcessSuccessDate] [datetime] NULL,
[ProcessSuccessUser] [datetime] NULL,
[FileTypeID] [int] NULL,
[HoldDate] [datetime] NULL,

2008 Tabela B Def

ProcessSuccessDate] [datetime] NULL,
[ProcessSuccessUser] [datetime] NULL,
[FileTypeID] [int] NULL,
[HoldDate] [datetime] NULL,

file.FileTypeID = (int)reader["FileTypeID"]; daje taki sam wynik.

Robiąc

     file.FileTypeID (int)reader.GetInt32(reader.GetOrdinal("FileTypeID"));

działa, ale nie chcę tego robić dla każdej kolumny, która już powinna powrócić jako int również pisząc takie sql

     select Convert(int, FileTypeID) as FileTypeId, delimeter, file_filetype.LocalPath, ArchiveDir, EmailList

może również obejść ten problem, ale chcę wiedzieć, dlaczego muszę to zrobić, jeśli już ustawiłem typ jako int w tabeli. Równie dobrze mogę umieścić wszystkie typy jako napisy w tabeli. W tym momencie nie szukam obejścia, chcę zrozumieć, dlaczego nie działa tak, jak powinien.


14
2018-06-11 15:38


pochodzenie


Czy komunikat o błędzie informuje, jakie typy były zaangażowane? Czy możesz opublikować pełny komunikat o błędzie? - Mark Byers
Jaka jest twoja instrukcja SQL? - Jon Senchyna
Jesteś pewien FileTypeID jest w rzeczywistości int (a nie a longitp.)? - Kirk Woll
Następnie najprawdopodobniej błąd pochodzi z kodu C #. Jakiego typu zdefiniowano plik file.FileTypeID? - KreepN
Czy możesz ponownie sprawdzić, czy schemat jest taki sam w twoich bazach danych 2000 i 2008? W tej chwili jedyną rzeczą, która ma sens, jest zmiana kolumny na a varchar. - Adam V


Odpowiedzi:


Pokazane są obie wyświetlone tabele int jako typ danych, ale wygląda na to, że są to dwie wersje tej samej tabeli w dwóch różnych bazach danych.

Wierzę, że INNA tabela, ta, którą ty JOIN to, ma inny typ danych w jednej bazie danych.

Jaki jest typ danych File_fileType.Id w obu DB?

Twój JOIN:

join file_filetype on file_importtable.FileTypeID = file_filetype.ID

Powoduje niejawną konwersję.

enter image description here

Powyższy wykres pokazuje, w jaki sposób SQL Server zezwala na lub wykonuje konwersje typów danych.

Czy możesz pokazać DDL dla obu wersji obu tabel w powyższym JOIN?


9
2018-06-08 20:29





Wydaje mi się, że istnieje pewne zwariowane ustawienie konfiguracji, które trudno będzie znaleźć. Istnieje narzędzie o nazwie Redgate Porównanie SQL to robi niesamowity praca przy wykrywaniu różnic między schematami bazy danych.

Mają 14-dniową próbę. Chciałbym spróbować pobrać i przeprowadzić porównanie między bazami danych.


6
2018-06-09 05:32





czy dopasowanie sortowania SQL jest zgodne? Jeśli doświadczasz różnych zachowań między bazami danych, może to być problem. Kliknij prawym przyciskiem myszy każdą bazę danych i wybierz właściwości, sortowanie powinno być określone jako coś w stylu * Latin1_General_CI_AS * Jeśli są różne, to zdecydowanie coś należy wykluczyć.


3
2018-06-11 15:00



Nie wiedziałbym, że tak, ale tak, niestety oba Collations pasują i są one SQL_Latin1_General_CP1_CI_AS - Micah Armantrout
OK, żeby sprawdzić typ danych w dopasowaniu db? - Liam
Tak Typy danych pasują, pokazałem to w pytaniu - Micah Armantrout
Czy próbowałeś dołączyć do swoich Db profillera serwera SQL, czy jest jakaś różnica w sposobie uruchamiania SQL? Czy używasz EXEC, gdzie jako drugi przetwarza SQL bezpośrednio? - Liam


Będziesz musiał rzucić z łańcucha.

file.FileTypeID = int.Parse((string)reader["FileTypeID"]);

EDYCJA: jeśli chcesz obejście, które powinno działać dla ZARÓWNO serwer sql 2008 i 2000

file.FileTypeID = Convert.ToInt32(reader["FileTypeID"]);

1



to jest świetne obejście, nie rozwiązuje prawdziwego problemu. - Micah Armantrout
@MicahArmantrout Nadal nie jest powodem do głosowania. - Danny Varod
jeśli nie odpowiada na pytanie - Micah Armantrout
Jeśli nie chcesz rzucić, podejrzewam, że będziesz musiał zmienić coś u swojego dostawcy, czy używasz JET lub standardowego dostawcy ADO.net? - Matthew
Używam System.Data.SqlClient Myślę, że byłoby dobrze - Micah Armantrout


Visual Studio (edycja Premium i Ultimate według to) zawiera narzędzie do porównywania baz danych - wybierasz dwie bazy danych, pokazuje różnicę i dajesz zestaw skryptów, które przenoszą jeden do drugiego stanu. Zacznij tam i spróbuj wyłowić konfigurację, która różni się (tak jak oczekiwałbym, że jest to problem z konfiguracją). Sprawdź dane \ Schema Porównaj i danych \ Porównaj danych w Visual Studio.


1





Wystąpienie co najmniej jednego błędu zostało już potwierdzone. Ponieważ nie mam całego obrazu, trudno jest być precyzyjnym. Dlatego sugeruję dwie kontrole.

Pierwsze sprawdzenie powinno dotyczyć obu baz danych przy użyciu INFORMATION_SCHEMA.COLUMNS (to więcej niż wystarczający poziom dla wymaganego poziomu), aby sprawdzić, czy schematy są identyczne. Możesz przeczytać więcej na temat INFORMATION_SCHEMA.COLUMNS at http://msdn.microsoft.com/en-us/library/aa933218(v=sql.80).aspx (SQL 2000) lub http://msdn.microsoft.com/en-us/library/ms188348 (SQL 2008). Te same informacje z różnych źródeł.

Próba:

SELECT * FROM INFORMATION_SCHEMA.COLUMNS;

Jeśli schematy są identyczne, może występować błąd w kodzie, który nie jest widoczny w prezentowanych częściach. Aby sprawić, że wszystko jest w porządku z tobą pełnym kodem, dokonaj prostej kontroli, zmieniając instrukcję select w następujący sposób:

select CAST(fileTypeID as int), ..., file_filetype.LocalPath, ArchiveDir, EmailList
from file_importtable 
join file_filetype on file_importtable.FileTypeID = file_filetype.ID
where importsuccessdate is null and transferdate is not null
and remotediscoverdate is not null 
and OriginalFileName in ('Test987.xml.pgp')

Jeśli się nie powiedzie, uruchom w trybie debugowania krok po kroku test używając punktu przerwania i F11. (Czasami powrót do korzeni może nam pomóc dostrzec to, co niewidzialne na naszych oczach - jest to mniej prawdopodobne w tym przypadku).

Postępując zgodnie z powyższym, znajdziesz przyczynę (miejmy nadzieję).

Ostatnia wskazówka (co może być pierwszym krokiem przed zrobieniem czegokolwiek innego): upewnij się, że twoje serwery sql są załatane najnowszymi dodatkami Service Pack.


1





W schemacie rzeczy postanowiłem usunąć tabelę i odtworzyć ją za pomocą

[tabela skryptów jako] -> [utwórz]

z tej samej tabeli, która dawała mi problemy, a następnie ponownie wprowadzono wszystkie te same dane. To rozwiązało problem. Nie wierzę, że DML tabeli zmienił się i dane również się nie zmieniły, ale to właśnie rozwiązało mój problem.


1





Widząc, że tego nie rozwiązałeś, być może spróbuj GetSqlInt32 zamiast tego metoda.

file.FileTypeID = reader.GetSqlInt32((fieldTypeIDOrdinal).ToNullableInt32();

Uwaga Nie uwzględniłem IsDBNull sprawdź od, łącząc SqlInt32 z ToNullableInt32 radzi sobie z tym.

Gdzie ToNullableInt32 jest metodą rozszerzenia.

public static int? ToNullableInt32(this SqlInt32 value)
{
    return value.IsNull ? (int?) null : value.Value;
}

Na marginesie wspomniałeś, że jest to aplikacja o priorytecie wydajności, w którym to przypadku możesz chcieć wstępnie oszacować wartości porządkowe zamiast tego reader.GetOrdinal("FileTypeID") każda twoja pętla reader.Read()


0



GetSqlInt32 nie rozwiązał tego problemu. - Micah Armantrout
Co za rozczarowanie! - Chris Moutray
Jestem prawie pewien, że coś jest nie tak z bazą danych lub ciągiem połączeń, ale nie jestem pewien co - Micah Armantrout
Tak, myślę, że to także ma coś wspólnego z konfiguracją bazy danych lub ciągiem połączeń / dostawcą danych. - Chris Moutray
Ciekawe, czy próbowałeś stworzyć prosty przykładowy projekt (np. Podstawowa aplikacja konsolowa) łączący się z prostą bazą danych, jedną tabelą, jedną kolumną, w której kolumna jest typu int? Mogłoby to spowodować w przeciągu 5 minut i może pomóc w wyodrębnieniu, że to jego kod lub baza danych ... - Chris Moutray


file.FileTypeID = Convert.ToInt32(reader["FileTypeID"]); zamiast file.FileTypeID = (int)reader["FileTypeID"];


0



To jest ta sama koncepcja, obejście, szukam powodu, dla którego rzeczy działają w ten sposób, aby nie zamiatać go pod dywan. Dzięki! - Micah Armantrout