Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc
Titulní Blogy Fotky Soubory

ZazaBlog

LINQ to SQL ano, ale ...

LINQ to SQL je skvělá volba. Bezpochyby. I naprostý amatér si "nakliká" DBML soubor a může používat objekty namísto toho, aby pracoval přímo s ADO.NET. Myšlenka jistě dobrá. Na LINQ to SQL nicméně existuje několik věcí, které mě při jeho používání nevýslovně štvou.

Výchozí hodnoty po inicializaci

Při návrhu databáze se pochopitelně vyhýbám hodnotám NULL všude, kde můžu, a často používám DEFAULT hodnoty. Takže, fragment, dejme tomu, tabulky faktur by mohl vypadat nějak takhle:

CREATE TABLE FAKTURA(

    ID int NOT NULL IDENTITY (1,1),

    DATUM datetime NOT NULL DEFAULT getdate(),

    CENA money NOT NULL DEFAULT 0,

    ODBERATEL varchar (50) NOT NULL DEFAULT 0,

    CONSTRAINT PK_FAKTURA PRIMARY KEY CLUSTERED (ID)

)

Z čehož mi LINQ vygeneruje DBML soubor s přibližně tímto obsahem:

<Table Name="dbo.FAKTURA" Member="FAKTURAs">

  <Type Name="FAKTURA">

    <Column Name="ID" AutoSync="Never" Type="System.Int32" DbType="Int NOT NULL" IsPrimaryKey="true" IsDbGenerated="true" CanBeNull="false" />

    <Column Name="DATUM" AutoSync="Never" Type="System.DateTime" DbType="DateTime NOT NULL" CanBeNull="false" />

    <Column Name="CENA" Type="System.Decimal" DbType="Money NOT NULL" CanBeNull="false" />

    <Column Name="ODBERATEL" Type="System.String" DbType="VarChar(50) NOT NULL" CanBeNull="false" />

  </Type>

</Table>

Poměrně hloupé, není liž pravda? Pochopitelně, při jakémkoli pokusu vytvořit fakturu následujícím způsobem skončíte na chybě:

Dim myFaktura As FAKTURA = New FAKTURA

myFaktura.DATUM = #1/1/2008#

d.FAKTURAs.InsertOnSubmit(myFaktura)

Try

  d.SubmitChanges()

Catch ex As Exception

  Debug.Print(ex.ToString)

End Try

z toho prostého důvodu, že jste neinicializovali některé vlastnosti, LINQ to SQL je nedoplnil, pokusil se poslat do databáze v jistých sloupcích hodnoty NULL a ono to selhalo. Řešení je sice prosté, máme partial classes, kde se to dá nainicializovat, ale kdo se s tím má otravovat?

Partial Class Faktura

  Private Sub OnCreated()

    Me.CENA = 0

    Me.DATUM = Today

    Me.ODBERATEL = ""

  End Sub

End Class

Máte někdo řešení, jak z toho ven?

Zveřejněno Wednesday, February 11, 2009 9:32 PM by xzajic
Vedeno pod:

Komentář

 

St Louis Rams napsal:

Great post!! thank you

February 12, 2009 7:13 AM
 

lukaashek napsal:

Pokud máš tedy v databázi sloupce s defaultní hodnotou, mělo by stačit v Design modu kliknout na příslušnou entitu a v properties každého atributu nastavit Auto Generated Value na true. Defaultně je to totiž nastaveno na false (LINQ to z nějakého důvodu sám nerozpozná)

February 13, 2009 5:42 PM
 

xzajic napsal:

Díky za tip, netušil jsem, že to takhle jde. Otázka je, co to řeší. Pokud totiž viz příklad výše vytvoříš fakturu, pak ji přiřadíš třeba datum "natvrdo" a uložíš ji s atributem IsDbGenerated="true" ve Tvém dmbl souboru, pak při INSERTU LINQ přepíše údaje "svými" získanými z databáze. Což mi přijde ještě o něco málo větší zmatek než při použití partial classes. Ale díky za postřeh.

February 13, 2009 5:58 PM
 

lukaashek napsal:

Jestli se nepletu tak v tomhle příkladu to může nstat nejenom při použití LINQ to SQL, ale třeba i klasicky ADO.NET. Řekl bych, že to už je pak jenom o návrhu db. Bud si tu položku nechám generovat serverem, či si jí vezmu do své režie :-)

February 13, 2009 7:40 PM
 

xzajic napsal:

Když použiješ klasické ADO.NET, tak a) té položce nastavíš datum z kódu a do databáze se uloží datum, které jsi nastavil, nebo b) tu položku necháš na NULL a databáze to "přepráskne" DEFAULT hodnotou.

Když použiješ LINQ to SQL tak a) té položce nastavíš datum z kódu, ale při IsDeGenerated="true" to program ignorije, nebo b) tu položku necháš na NULL a databáze při uložení selže.

Dá se s tím žít, ale moc systémové mi to nepřijde.

February 14, 2009 5:32 AM
Neregistrovaní uživatele nemužou přidávat komentáře.
Powered by Community Server (Personal Edition), by Telligent Systems