Menukar pengekodan rentetan daripada Unicode kepada ASCII. Menggunakan Penyesuai Kursor

Apa itu IDENTITI

IDENTITY bukan jenis data. Ini adalah beberapa harta tambahan, had yang dikenakan jenis integer data dalam pelayan MS SQL. Itu. sifat ini boleh digunakan pada medan jenis berikut: tinyint, smallint, int, bigint, perpuluhan(p,0), atau angka(p,0)

Setara dengan sifat ini dalam FoxPro ialah jenis data Integer-AutoIncrement. Cuma jangan anggap bahawa Integer-AutoIncrement ialah medan dengan sifat Identiti. Tidak sama sekali. Ini betul-betul analog. Mereka pada asasnya serupa, tetapi mempunyai beberapa perbezaan. Dalam artikel ini kita akan bercakap tentang sifat IDENTITY dalam pelayan MS SQL.

Medan dengan sifat IDENTITY mempunyai ciri berikut:

  • Dalam satu jadual, hanya satu medan dengan sifat IDENTITY dibenarkan
  • Medan dengan sifat IDENTITY tidak boleh diedit. Mereka mempunyai harta baca sahaja.
  • Medan dengan sifat IDENTITY diberikan nilai secara automatik apabila rekod baharu dibuat.

Terdapat beberapa ciri lain, tetapi ia sudah menjadi akibat daripada ciri yang disenaraikan

Nilai baharu ialah nilai terakhir yang digunakan ditambah beberapa nilai tetap. Sila ambil perhatian bahawa nilai baharu tidak berdasarkan nilai maksimum dalam rekod sedia ada, dan kepada nilai yang terakhir digunakan. Ini bermakna rekod dengan nilai terakhir yang digunakan mungkin tidak wujud secara fizikal, tetapi nilai itu masih akan digunakan.

Dalam erti kata lain, "lubang" agak boleh diterima dalam jujukan nilai medan dengan sifat IDENTITI. Senarai nilai tidak berterusan sama sekali

Biasanya, langkah kenaikan ialah 1, tetapi ia boleh menjadi sebarang integer. Termasuk yang negatif.

Disebabkan oleh ciri-ciri medan dengan sifat IDENTITY ini, medan sedemikian sering digunakan sebagai kunci utama. Dalam erti kata lain, sebagai medan yang nilainya sentiasa boleh mengenal pasti rekod jadual secara unik.

Perlu diingat bahawa sifat IDENTITY tidak mengawal keunikan data dalam apa jua cara. Sebagai contoh, jika medan pada mulanya mempunyai taip INTEGER, dan beberapa nilai telah dimasukkan ke dalamnya. Dan kemudian struktur jadual telah ditukar, dan sifat IDENTITY digunakan pada medan ini, maka rekod baharu mungkin mempunyai data yang sama yang telah dimasukkan ke dalam jadual ini sebelum ini. Oleh itu, jika medan dengan sifat IDENTITY digunakan sebagai kunci utama, maka medan ini harus ditindih sekatan tambahan oleh keunikan.

Kelemahan menggunakan medan dengan sifat IDENTITY sebagai kunci utama

Walau bagaimanapun, walaupun terdapat kelebihan jelas menggunakan medan dengan sifat IDENTITY sebagai kunci utama, medan tersebut juga mempunyai kelemahan yang serius.

Nilai medan dengan sifat IDENTITY tidak boleh diketahui sehingga rekod dibuat secara fizikal.

Jadi apa? Apa masalah? Mari buat rekod dan ketahui nilai baharunya.

Masalahnya ialah untuk mengetahui nilai medan dalam rekod, rekod ini mesti dicari terlebih dahulu. Dan carian untuk rekod dijalankan dengan tepat oleh nilai kunci utama. Yang nilainya perlu ditentukan. Lingkaran ganas: untuk membaca nilai yang anda perlukan untuk mengetahui nilai ini!

Struktur storan data dalam pelayan MS SQL pada asasnya berbeza daripada struktur storan data dalam fail DBF. Tidak ada konsep seperti " nombor fizikal rekod", " entri seterusnya", "rekod terakhir", dll. Iaitu, adalah mustahil untuk pergi ke "rekod terakhir" untuk membaca nilai kunci utamanya.

Selain itu, walaupun nilai baharu medan dengan sifat IDENTITY sentiasa lebih besar daripada mana-mana nilai sedia ada (jika kenaikannya adalah nombor positif), tetapi juga mustahil untuk menentukan nilai baharu ini dengan hanya mengira maksimum nilai sedia ada. Tidak, nilai maksimum itu sendiri, sudah tentu, akan diperolehi. Tiada jaminan bahawa nilai yang terhasil ialah nilai rekod tepat yang dibuat.

Maksudnya di sini ialah, sebagai peraturan, pelayan MS SQL digunakan dalam aplikasi berbilang pengguna. Ini bermakna beberapa pengguna boleh mencipta rekod baharu pada masa yang sama. Ternyata seorang pengguna telah mencipta entri baru, kemudian mula mengira nilai maksimum dan pada ketika itu pengguna lain turut mencipta entri baharu. Hasilnya, pengguna pertama akan menerima nilai rekod yang dibuat oleh pengguna kedua sebagai nilai maksimum.

Jadi patutkah kita berhenti menggunakan medan dengan sifat IDENTITY sebagai kunci utama? Tidak sama sekali. Namun, terdapat cara untuk menentukan nilai medan dengan sifat IDENTITI rekod baharu.

Cara menentukan nilai medan dengan sifat IDENTITY dalam rekod baharu

Sebenarnya, terdapat tiga strategi asas untuk menentukan nilai medan dengan sifat IDENTITI dalam rekod baharu yang baru dibuat.

Sekarang mari kita lihat dengan lebih dekat kelebihan dan kekurangan setiap strategi.

Nilai yang dikembalikan oleh pembolehubah sistem @@IDENTITY

MS SQL Server mempunyai beberapa pembolehubah sistem, yang nilainya berubah secara automatik apabila peristiwa tertentu berlaku. Khususnya, nilai pembolehubah sistem @@IDENTITY ditetapkan secara automatik kepada nilai medan dengan sifat IDENTITY rekod terakhir yang dibuat dalam sambungan semasa. Itu. penciptaan entri baharu dalam sambungan lain (oleh pengguna lain) tidak akan menjejaskan nilainya dalam apa jua cara dalam hubungan ini.

Nah, inilah penyelesaiannya. Hanya selepas mencipta rekod baharu, kami membaca nilai pembolehubah sistem @@IDENTITY dan mempunyai nilai yang dikehendaki.

Secara umum, benar. Satu-satunya masalah ialah pembolehubah sistem @@IDENTITY menukar nilainya apabila membuat entri masuk mana-mana meja.

Dalam amalan, ini bermakna jika pencetus sisipan dipasang pada jadual, badan yang mengandungi arahan INSERT untuk mencipta rekod dalam jadual lain, yang, seterusnya, juga mempunyai medan dengan sifat IDENTITI, kemudian @@ Pembolehubah sistem IDENTITI akan menerima nilai medan daripada jadual kedua ini.

Dalam erti kata lain, anda boleh bergantung pada nilai pembolehubah sistem @@IDENTITY, tetapi ingat bahawa pembolehubah ini tidak terikat dengan nilai medan dalam satu jadual.

Nilai pulangan daripada SCOPE_IDENTITY()

Dalam versi MS SQL 2000 ia diperkenalkan fungsi sistem SCOPE_IDENTITY(). Fungsi ini juga mengembalikan nilai medan dengan sifat IDENTITY rekod terakhir yang dibuat, tetapi dibuat dalam SKOP semasa.

Agak sukar untuk menterjemahkan istilah SKOP ke dalam bahasa Rusia dengan secukupnya. Tetapi, lebih kurang, kita boleh katakan ini: SKOP ialah satu prosedur atau fungsi. Dalam erti kata lain, SCOPE_IDENTITY() akan mengembalikan nilai medan dengan sifat IDENTITY rekod terakhir yang dibuat dalam prosedur di mana fungsi ini dipanggil.

Pencetus sudah menjadi SKOP yang berbeza (fungsi lain), jadi ia tidak akan menjejaskan nilai yang dikembalikan oleh SCOPE_IDENTITY().

Walaupun dua pengguna memanggil prosedur yang sama pada masa yang sama, tetapi masing-masing memanggil prosedur dalam SKOP mereka sendiri. Itu. sekali lagi tiada konflik.

Kelemahan fungsi ini ialah ia harus dipanggil dalam SKOP di mana rekod baru jadual yang menarik kepada kami telah dicipta. Dan ini tidak selalu mungkin.

Dalam erti kata lain, untuk menggunakan SCOPE_IDENTITY() dengan betul, anda mesti sentiasa mengetahui skop SCOPE. Selalunya dengan membuat prosedur khas.

Mencari rekod baharu mengikut nilai medan lain

Jika anda masih ingat, masalah utama dalam menentukan nilai medan dengan sifat IDENTITY ialah medan ini digunakan sebagai kunci utama. Itu. Berdasarkan nilainya, entri yang diperlukan ditemui.

Walau bagaimanapun, jadual selalunya mempunyai medan atau set medan yang juga boleh digunakan untuk mengenal pasti rekod secara unik. Sebagai contoh, jika kita bercakap tentang mengenai direktori, maka, sudah tentu, direktori itu mempunyai medan "Nama". Ia juga jelas bahawa medan ini mestilah unik dalam direktori. Jika tidak, tujuan menggunakan buku rujukan itu sendiri hilang begitu saja. Mengapa memasukkan entri ke dalam direktori dengan nilai yang sama?

Mengapa tidak menggunakan "Nama" ini sebagai kunci utama? Mengapa anda memerlukan medan dengan sifat IDENTITY? Ini adalah topik untuk perbincangan lain. Ringkasnya, "Nama" adalah untuk pengguna (data luaran) dan IDENTITI adalah untuk memastikan integriti rujukan pangkalan data (data dalaman).

Nilai medan dengan sifat IDENTITY dalam rekod baharu tidak diketahui. Tetapi maksud medan Tajuk dalam rekod baru ini agak diketahui. Pengguna memasukkannya sendiri! Ini bermakna selepas mencipta rekod baharu, anda boleh mencari rekod baharu ini mengikut nilai medan "Nama" dan membaca nilai medan dengan sifat IDENTITY.

Satu-satunya masalah ialah medan atau set medan sedemikian tidak selalu wujud untuk mengenal pasti rekod secara unik. Ini, dengan cara ini, adalah salah satu sebab untuk memasukkan kunci pengganti yang dipanggil. Medan yang sama dengan sifat IDENTITY.

Walau bagaimanapun, jika anda memutuskan untuk menggunakan strategi ini untuk mencari rekod baharu, pastikan anda mengenakan kekangan keunikan pada medan "Tajuk" (atau set medan yang anda pilih). Iaitu, supaya tidak ada dua rekod dengan nilai yang sama dalam medan ini secara kebetulan.

Cara bekerja dengan medan dengan sifat IDENTITY dalam FoxPro

Kami telah selesai dengan bahagian teori, kini "mari kita cuba melepaskan semua perkara ini." Itu. Mari tentukan cara menggunakan semua pengetahuan ini dalam FoxPro. Mari kita perjelaskan sekali lagi masalah yang perlu diselesaikan.

Rekod ditambahkan pada jadual pelayan MS SQL yang mempunyai medan dengan sifat IDENTITY. Sejurus selepas mencipta rekod baharu, anda perlu mendapatkan nilai medan dengan sifat IDENTITI di sebelah FoxPro.

FoxPro mempunyai tiga pilihan asas untuk mengatur kerja dengan pelayan MS SQL

  • Menggunakan Pandangan Jauh
  • Menggunakan Penyesuai Kursor

Di sini kita harus memikirkan peristiwa yang sebenarnya mencipta rekod pada pelayan MS SQL. Nah, semuanya jelas dengan Pass-Trough. Ini sebenarnya adalah arahan terus kepada pelayan untuk mencipta rekod baharu. Tetapi dengan Pandangan Jauh dan Penyesuai Kursor ia sedikit berbeza.

Hasil kedua-dua Paparan Jauh dan Penyesuai Kursor ialah kursor. Itu. meja sementara yang terletak secara fizikal pada mesin pelanggan. Secara lalai, kursor ini dibuka secara automatik dalam mod penimbalan baris optimistik (3) dan hanya boleh ditukar kepada mod penimbalan jadual optimistik (5). Adalah mustahil untuk menukar kepada mod penimbalan pesimis atau melumpuhkan penimbalan sepenuhnya untuk kursor ini

Akibatnya, rekod baharu akan dibuat secara fizikal pada mesin klien dalam kursor ini. Lebih tepat lagi, dalam penimbal kursor ini. Penciptaan fizikal rekod pada pelayan MS SQL akan berlaku hanya selepas penimbal ditetapkan semula.

Untuk penimbalan talian, siram penimbal boleh berlaku secara automatik apabila anda melakukan salah satu daripada yang berikut:

  • Melompat (atau cuba melompat) ke entri lain
  • Menutup kursor
  • Bertukar kepada mod penimbalan jadual
  • Dengan arahan TableUpdate().

Untuk penimbalan jadual, penimbal hanya boleh dibilas menggunakan perintah TableUpdate() dan tiada yang lain.

Tiada tindakan atau operasi lain dengan Paparan Jauh atau Penyesuai Kursor akan membawa kepada penciptaan rekod baharu pada pelayan MS SQL. Jika, semasa menjalankan sebarang operasi, ternyata rekod baharu telah dibuat pada pelayan MS SQL, ini bermakna kursor berada dalam mod penimbalan baris, dan salah satu peristiwa yang menyebabkan tetapan semula penimbal automatik berlaku.

Sebagai contoh, ini boleh berlaku dengan perintah Requery() untuk Paparan Jauh. Tetapi ini tidak bermakna arahan Requery() mengepam penimbal. Tidak sama sekali. Ringkasnya, salah satu syarat untuk melaksanakan perintah Requery() ialah menutup kursor sedia ada sebelum ini. Tetapi peristiwa ini akan menyebabkan tetapan semula penimbal automatik jika kursor berada dalam mod penimbalan baris.

Untuk mengelakkan salah faham seperti itu, tukar kursor kepada mod penimbalan jadual (5). Dalam kes ini, anda akan sentiasa dapat mengawal proses tetapan semula penimbal.

Walau bagaimanapun, anda harus faham bahawa walaupun anda menetapkan mod penimbalan jadual, tukar beberapa rekod dalam Paparan Jauh atau Penyesuai Kursor, dan kemudian keluarkan arahan TableUpdate(), penimbal masih akan dipadamkan satu rekod pada satu masa. Itu. Bukan satu arahan akan dihantar ke pelayan, contohnya, untuk pengubahsuaian, tetapi satu set arahan untuk mengubah suai setiap rekod secara berasingan.

Berhubung dengan operasi mencipta rekod baharu, ia berikutan bahawa dalam semua peristiwa objek Penyesuai Kursor Sentiasa Hanya satu rekod dimasukkan pada satu masa.

Penggunaan terus teknologi Pass-Through melalui fungsi SQLEXEC().

Dengan kaedah kerja ini, pengaturcara bekerja secara langsung dengan pelayan MS SQL. Ia menjana semua arahan yang dihantar ke pelayan, menerima hasilnya, dan memprosesnya sendiri. Dalam kes ini, tidak sukar untuk menghantar permintaan tambahan kepada pelayan untuk nilai fungsi SCOPE_IDENTITY

LOCAL lcNewValue, lnResut lcNewValue = "Nilai baharu" lnResut = SQLExec(m.lnConnectHandle,"INSERT INTO MyTab (Field1) VALUES (?m.lcNewValue)") IF m.lnResut>0 SQLExec(m.lnConnectHandle,"SELECT NewIdent=SCOPE_IDENTITY()","NewIdent") ?NewIdent.NewIdent ELSE LOCAL laError(1) =AERROR(laError) * Анализ массива laError для уточнения причины ошибки ENDIF !}

DALAM dalam contoh ini m.lnConnectHandle ialah nombor, nombor sambungan ke pelayan MS SQL, yang dikonfigurasikan lebih awal. MyTab ialah jadual yang mempunyai medan dengan sifat IDENTITY.

Selepas melaksanakan pertanyaan kedua dalam kursor NewIdent yang terhasil dalam medan NewIdent rekod pertama kami mendapat nilai yang dikehendaki. Dalam sintaks ini, kedua-dua arahan sisip dan panggilan ke fungsi SCOPE_IDENTITY() berlaku dalam SKOP yang sama. Oleh itu, kita mendapat nilai yang dikehendaki.

Menggunakan Pandangan Jauh

Pandangan Jauh ialah sejenis "tambahan" kepada teknologi Lulus. Pada asasnya, apabila mencipta rekod baharu, arahan INSERT INTO yang sama dilaksanakan. Walau bagaimanapun, masalahnya ialah walaupun kita membaca nombor sambungan yang Paparan Jauh sedang berjalan dan kemudian menjalankan pertanyaan untuk menentukan nilai yang dikembalikan oleh SCOPE_IDENTITY(), kita akan mendapat NULL kerana dalam kes ini arahan sisip dan SCOPE_IDENTITY() adalah dilaksanakan dalam SKOP yang berbeza. Oleh itu, hanya terdapat dua cara untuk menentukan nilai medan dengan sifat IDENTITY.

* Menentukan nilai pembolehubah sistem @@IDENTITY LOCAL lnConnectHandle lnConnectHandle = CursorGetProp("ConnectHandle","MyRemoteView") SQLExec(m.lnConnectHandle,"SELECT NewIdent=@@IDENTITY","NewIdent") ?NewIdenting.NewIdent * Determining dengan nilai medan lain LOCAL lnConnectHandle, lcNickName lnConnectHandle = CursorGetProp("ConnectHandle","MyRemoteView") lcNickName = MyRemoteView.NickName SQLExec(m.lnConnectHandle,"SELECTNadent TabId FROM MyTab"lc" NewIdent.T abId

Dalam kedua-dua contoh, MyRemoteView ialah nama Paparan Jauh anda. Nama Panggilan ialah nama medan dalam Paparan Jauh mengikut nilai yang mana rekod baharu dicari dan TabID ialah medan yang sama dengan sifat IDENTITY yang nilainya mesti ditentukan

Diandaikan bahawa penciptaan rekod baru telah pun berlaku. Sama ada arahan TableUpdate() telah dikeluarkan secara eksplisit atau Paparan Jauh berada dalam mod penimbalan baris dan percubaan telah dibuat untuk beralih ke rekod lain.

Dan mengapa dalam kes kedua bukan penyelesaian carian yang kelihatan lebih jelas digunakan selepas Requery()? Sesuatu seperti

REQUERY("MyRemoteView") SELECT MyRemoteView LOCATE FOR Nickname = "New value" ?MyRemoteView.TabID

Terdapat beberapa sebab untuk ini.

Pertama, Requery() melibatkan pelaksanaan semula pertanyaan. Itu. Diandaikan bahawa penimbal semua entri Paparan Jauh telah dibuang. Tetapi ini mungkin tidak berlaku. Sebagai contoh, mereka mengepam penimbal satu rekod pada satu masa dalam gelung.

Kedua, biasanya Remote View mengandungi syarat-syarat tambahan pemilihan rekod, dan rekod yang baru dibuat mungkin tidak termasuk dalam syarat pemilihan sama sekali. Itu. selepas Requery(), rekod, walaupun ia akan dibuat secara fizikal pada pelayan, tidak akan dipaparkan dalam Remote View itu sendiri.

Menggunakan Penyesuai Kursor

Objek Penyesuai Kursor telah diperkenalkan ke dalam FoxPro bermula dengan Visual FoxPro 8. Ia direka bentuk untuk memudahkan untuk bekerja dengan data jauh apabila melakukan beberapa operasi biasa. Khususnya, operasi mencipta rekod baharu. Melalui Penyesuai Kursor, anda boleh melaksanakan ketiga-tiga pilihan untuk mendapatkan nilai medan dengan sifat IDENTITY dalam rekod baharu.

Nilai yang dikembalikan oleh pembolehubah sistem @@IDENTITY

Selepas penimbal ditetapkan semula dan rekod baharu dibuat secara fizikal pada pelayan MS SQL, acara AfterInsert akan menyala dalam objek Penyesuai Kursor. Di sinilah anda perlu membuat permintaan tambahan kepada pelayan dan membaca nilai pembolehubah sistem @@IDENTITY

PROSEDUR AfterInsert LPARAMETERS cFldState, lForce, cInsertCmd, lResult JIKA lResult=.T. && pemasukan telah berjaya. Kita perlu mendapatkan nilai ID LOCAL currentArea currentArea=SELECT() CUBA JIKA 1=SQLEXEC(this.DataSource,"SELECT NewIdent=@@IDENTITY","NewIdent") GANTIKAN TabId DENGAN NewIdent.NewIdent IN (This.Alias) USE IN IDRes ELSE LOCAL laError(1) =AERROR(laError) * Analisis tatasusunan laError untuk menentukan punca ralat ENDIF FINALLY SELECT (currentArea) ENDTRY ENDIF ENDPROC

Saya rasa kod itu agak jelas dan tidak memerlukan penjelasan. Selepas berjaya mencipta rekod baharu pada pelayan menggunakan SQLExec() untuk sambungan yang sama, kami menentukan nilai @@IDENTITY dan menulis nilai ini pada rekod kursor semasa dalam medan kekunci.

Dalam Visual FoxPro 9, harta telah ditambahkan pada objek Penyesuai Kursor InsertCmdRefreshCmd. Ini ialah arahan yang dihantar ke pelayan hanya selepas rekod baru berjaya dimasukkan. Itu. tidak perlu mengesahkan bahawa rekod baharu telah dibuat.

Dipasangkan dengan hartanah baharu yang lain InsertCmdRefreshFieldList Anda boleh melakukan kemas kini berdasarkan nilai pembolehubah sistem @@IDENTITY dengan lebih mudah. Untuk melakukan ini, anda hanya perlu membuat tetapan berikut untuk objek CursorAdapter

CursorAdapter.InsertCmdRefreshCmd = "SELECT @@IDENTITY" CursorAdapter.InsertCmdRefreshFieldList = "TabId"

Di sini TabId bukanlah nama medan dengan sifat IDENTITY dalam jadual itu sendiri pada pelayan MS SQL, tetapi nama medan kursor yang diterima pada sisi klien di mana kandungan medan dengan sifat IDENTITY dipaparkan. Sebagai peraturan, nama-nama ini adalah sama, tetapi, secara umum, mereka mungkin berbeza. Butiran lanjut tentang hartanah InsertCmdRefreshFieldList baca dibawah. Dalam bahagian mencari rekod baharu berdasarkan nilai medan lain.

Nilai pulangan daripada SCOPE_IDENTITY()

Di sini semuanya lebih rumit. Intinya ialah anda tidak boleh bertindak dengan cara yang sama seperti dalam hal menentukan pembolehubah sistem @@IDENTITY. SQLExec() dan Penyesuai Kursor beroperasi dalam SKOP yang berbeza. Oleh itu, dengan pendekatan ini, SCOPE_IDENTITY() akan sentiasa mengembalikan NULL. Untuk mengatasi percanggahan ini, prosedur khas digunakan.

Sebagai permulaan, anda perlu mencipta prosedur tersimpan berikut pada pelayan MS SQL itu sendiri

BUAT PROSEDUR Get_ValueInt @ValueIn Int, @ValueOut Int OUTPUT SEBAGAI SET NOKA PADA PILIHAN @ValueOut=@ValueIn

Seperti yang anda lihat, tujuan prosedur ini hanyalah untuk menetapkan nilai parameter input kepada parameter output. Anda kini boleh menggunakan prosedur ini untuk menentukan nilai SCOPE_IDENTITY() dalam Penyesuai Kursor. Untuk melakukan ini dalam acara itu BeforeInsert penggantian sedemikian sedang dibuat

PROSEDUR SebelumMasukkan LPARAMETERS cFldState, lForce, cInsertCmd cInsertCmd = cInsertCmd + ; "; ISYTIHKAN @id int" + ; "; SELECT @id=SCOPE_IDENTITY()" + ; "; EXEC Get_ValueInt @id, [e-mel dilindungi]"ENDPROC

Perlu diingat bahawa dalam penggantian ini, MyTab bukan lagi nama jadual pada pelayan MS SQL, tetapi nama kursor yang dibuat pada klien. Lebih tepat lagi, nama yang tertulis dalam sifat Alias ​​Penyesuai Kursor itu sendiri. Sehubungan itu, "TabId" ialah nama medan kursor yang dibuat pada klien dan mengandungi nilai medan dengan sifat IDENTITY

DALAM dalam kes ini, pada dasarnya, prosedur tersimpan dinamik dihasilkan. Itu. bukan hanya satu arahan INSERT, tetapi urutan arahan. Perintah dipisahkan antara satu sama lain dengan koma bertitik, walaupun ini tidak perlu. Ia cukup untuk memisahkan arahan antara satu sama lain dengan ruang yang mudah.

Mencari rekod baharu mengikut nilai medan lain

Jika anda mempunyai Visual FoxPro 8, maka anda boleh menggunakan kaedah yang serupa dengan kaedah yang digunakan untuk mencari nilai pembolehubah sistem @@IDENTITY. Itu. dalam kaedah AfterInsert objek Penyesuai Kursor, lakukan pertanyaan tambahan melalui SQLExec()

Bermula dengan Visual FoxPro 9, objek Penyesuai Kursor mempunyai sifat tambahan yang membolehkan anda mengautomasikan prosedur ini tanpa menulis kod tambahan

InsertCmdRefreshFieldList- senarai medan yang nilainya akan dikemas kini selepas Sisipkan
InsertCmdRefreshKeyFieldList- medan, atau satu set medan bukan kunci yang juga mengenal pasti rekod secara unik, yang akan digunakan untuk mencari rekod baharu

Perlu diingatkan bahawa sifat ini tidak menunjukkan nama medan jadual pelayan MS SQL itu sendiri, tetapi nama medan sepadan kursor yang diterima di sebelah klien. Untuk contoh yang sama ia akan kelihatan seperti ini:

InsertCmdRefreshFieldList = "TabID" InsertCmdRefreshKeyFieldList = "NickName"

Dalam erti kata lain, berdasarkan nilai medan Nama Panggilan, rekod akan ditemui dalam jadual pada pelayan MS SQL dan nilai medan TabID akan dibaca, selepas itu nilai ini akan ditulis kepada rekod baharu pada pihak pelanggan.


Anda boleh melihat perbincangan yang lebih terperinci tentang topik ini dan contoh penggunaan di sini



Vladimir Maksimov
Kemas kini terakhir: 05/01/06

Anda telah melihat beberapa konvensyen konfigurasi yang digunakan oleh pendekatan ini. Khususnya, anda melihat cara untuk menyesuaikan model entiti menggunakan anotasi data yang dinyatakan melalui atribut C# dan menggunakan Fluent API. Dalam artikel ini dan seterusnya, kami akan melihat dengan lebih dekat cara ini untuk menyesuaikan model data anda.

Menetapkan Jenis Lajur

Terdahulu dalam kes penggunaan Kod-First, anda melihat penggunaan atribut metadata tertentu yang membenarkan anda menyesuaikan jenis data lajur dalam jadual pangkalan data dan menggunakan sekatan padanya (contohnya, menentukan sama ada ia menyokong nilai NULL). Kami akan melihat atribut ini dengan lebih terperinci seterusnya.

Had panjang

Jadual di bawah menunjukkan konvensyen untuk mengehadkan panjang lajur, pelaksanaannya sebagai anotasi dan dalam Fluent API:

Sekatan panjang boleh dikenakan pada rentetan atau tatasusunan bait. Menurut konvensyen, Code-First hanya menggunakan kekangan panjang maksimum, maksudnya begitu Pelayan SQL menetapkan jenis data untuk tatasusunan rentetan dan bait kepada NVARCHAR(n) dan VARBINARY(n), dengan n ialah panjang yang dinyatakan dalam kekangan. Secara lalai, jika tiada kekangan panjang telah digunakan pada sifat model, Code-First akan menetapkan panjang lajur maksimum yang mungkin kepada NVARCHAR(maks) dan VARBINARY(maks).

Seperti yang ditunjukkan dalam jadual, menggunakan anotasi data, anda boleh menetapkan panjang minimum untuk sifat model menggunakan atribut MinLength - sekatan ini tidak mempunyai kesan pada jadual pangkalan data. (Seperti yang diterangkan sebelum ini, atribut metadata boleh digunakan bukan sahaja dalam Rangka Kerja Entiti, tetapi, sebagai contoh, juga dalam pengesahan model ASP.NET.) Inilah sebabnya Fluent API tidak mempunyai kaedah HasMinLength(), kerana API ini adalah sebahagian daripada Rangka Kerja Entiti dan bertanggungjawab untuk menyediakan konvensyen yang berkaitan dengan Kod-Pertama sahaja.

Perlu diingat bahawa anda boleh menentukan panjang medan maksimum dan minimum dalam satu atribut StringLength, menggunakan parameter bernama atribut ini. Contoh berikut menunjukkan penggunaan sekatan panjang menggunakan anotasi (di sini kami menggunakan model contoh yang kami buat dalam artikel "Menggunakan Kod-Pertama" sebelum ini):

Menggunakan Sistem; menggunakan System.Collections.Generic; menggunakan System.ComponentModel.DataAnnotations; ruang nama CodeFirst ( Pelanggan kelas awam ( public int CustomerId ( get; set; ) rentetan awam FirstName ( get; set; ) rentetan awam Nama Akhir ( get; set; ) rentetan awam E-mel ( get; set; ) public int Age ( get; set ; ) bait awam Foto ( dapatkan; set; ) // Pautan ke pesanan Senarai maya awam Pesanan ( dapatkan; set; ) ) Pesanan kelas awam ( public int OrderId ( get; set; ) rentetan awam ProductName ( get; set; ) rentetan awam Penerangan ( get; set; ) public int Kuantiti ( get; set; ) public DateTime PurchaseDate ( get; set; ) // Pautan kepada pembeli Pelanggan Pelanggan awam (dapat; set; ) ) )

Dan dalam kod berikut, persediaan serupa dibuat menggunakan API Fasih (biar saya ingatkan anda bahawa untuk menggunakan API ini, anda perlu mengatasi kaedah konfigurasi OnModelCreating() dalam kelas konteks, yang dalam contoh kami ialah kelas SampleContext):

().Property(c => c.FirstName).HasMaxLength(30); modelBuilder.Entity ().Property(c => c.Emel).HasMaxLength(100); modelBuilder.Entity ().Property(o => o.ProductName).HasMaxLength(500); )

Menentukan jenis lajur secara eksplisit

Seperti yang diterangkan sebelum ini, Rangka Kerja Entiti secara automatik memetakan jenis data model kepada jenis data yang serasi dengan SQL. Code-First membolehkan anda mengawal proses ini dengan menyatakan secara eksplisit jenis data untuk lajur, seperti yang ditunjukkan dalam contoh di bawah:

Pelanggan kelas awam ( public int CustomerId ( get; set; ) // ... public byte Photo ( get; set; ) // ... ) // sama dengan Fluent API protected override void OnModelCreating(DbModelBuilder modelBuilder) ( modelBuilder. Entiti ().Property(c => c.CustomerId) .HasColumnType("smallint"); modelBuilder.Entity ().Property(c => c.Photo) .HasColumnType("imej"); )

Sokongan NULL lajur

Konvensyen Rangka Kerja Entiti untuk menyokong nilai nol dalam lajur jadual ialah semua jenis .NET yang menyokong null (objek) memetakan kepada jenis SQL dengan klausa NULL yang eksplisit, dan sebaliknya untuk jenis .NET yang tidak menyokong null ( struktur ) dipetakan kepada jenis SQL dengan menyatakan secara eksplisit pernyataan NOT NULL.

Untuk menunjukkan secara jelas bahawa jenis data mesti tidak menyokong nilai NULL, anda perlu menggunakan atribut Diperlukan dalam model data atau menggunakan kaedah IsRequired() bagi objek konfigurasi dalam Fluent API. Untuk menunjukkan secara eksplisit bahawa jenis data mesti menyokong nilai NULL, anda perlu menggunakan koleksi Nullable atau gunakan sintaks C#, yang untuk jenis nilai yang menyokong null termasuk tanda soal selepas jenis (contohnya, int?).

Contoh di bawah menunjukkan penggunaan tetapan ini untuk mengkonfigurasi maklumat tentang jenis nullable atau non-nullable dalam jadual pangkalan data:

Pelanggan kelas awam ( public int CustomerId ( get; set; ) rentetan awam FirstName ( get; set; ) rentetan awam LastName ( get; set; ) // Medan ini boleh menjadi NULL // kerana kami menyatakan secara eksplisit jenis int? int awam? Umur ( dapatkan; set; ) // Serupa dengan harta awam Nullable sebelumnya Age1 ( dapatkan; set; ) // ... ) // sama dengan Fluent API protected override void OnModelCreating(DbModelBuilder modelBuilder) ( modelBuilder.Entity ().Property(c => c.FirstName).IsRequired(); modelBuilder.Entity ().Property(c => c.LastName).IsRequired(); )

Sila ambil perhatian bahawa Fluent API hanya boleh dikonfigurasikan untuk menyokong NOT NULL untuk jenis data rujukan, dan tidak boleh dikonfigurasikan untuk menyokong NULL untuk jenis nilai kerana Sokongan NULL untuk mereka ditunjukkan secara eksplisit apabila mengisytiharkan jenis harta dalam kelas model.

Menetapkan kunci utama

Rangka Kerja Entiti memerlukan setiap kelas model entiti mempunyai kunci unik (kerana setiap jadual dalam pangkalan data hubungan data mesti digunakan kunci utama). Kunci ini digunakan dalam objek konteks untuk menjejaki perubahan pada objek model. Code-First membuat beberapa andaian apabila mencari kunci dalam jadual. Sebagai contoh, apabila kami menjana pangkalan data untuk kelas entiti Pelanggan dan Pesanan lebih awal dalam pendekatan Kod-Pertama, Rangka Kerja Entiti menandakan medan CustomerId dan OrderId dalam jadual sebagai kunci utama dan menetapkannya untuk menyokong jenis tidak boleh dibatalkan:

EF juga secara automatik menambah sokongan untuk kenaikan automatik dalam medan ini (biar saya ingatkan anda bahawa dalam T-SQL ini dilakukan menggunakan pernyataan IDENTITY). Selalunya, kunci utama dalam pangkalan data adalah jenis INT atau GUID, walaupun ada jenis primitif boleh digunakan sebagai kunci utama. Kunci utama dalam pangkalan data boleh terdiri daripada berbilang lajur jadual, begitu juga, kunci model entiti EF boleh terdiri daripada berbilang sifat model. Kemudian anda akan melihat bagaimana untuk menyediakan kunci komposit.

Menetapkan kunci utama secara eksplisit

Dalam kes dua kelas Pelanggan dan Pesanan kami, tidak perlu risau tentang menentukan kunci utama secara eksplisit, kerana Kami menggunakan sifat CustomerId dan OrderId, yang mengikut konvensyen penamaan utama - "+Id". Mari lihat contoh di mana anda perlu menentukan kunci primer secara eksplisit. Tambahkan kelas mudah berikut pada fail model anda:

Projek kelas awam ( Pengecam Panduan awam ( get; set; ) public DateTime StartDate ( get; set; ) public DateTime EndDate ( get; set; ) public decimal Kos ( get; set; ) )

Matlamat kami adalah untuk menunjukkan bahawa sifat Pengecam dalam kelas ini ialah kunci utama jadual. Seperti yang anda lihat, nama sifat ini tidak mengikut konvensyen penamaan Rangka Kerja Entiti untuk kunci utama.

Tambahkan perihalan jadual baharu pada kelas konteks SampleContext:

Kelas awam SampleContext: DbContext ( // ... public DbSet Projek ( dapatkan; set; ) // ... )

Sekarang, jika anda menjalankan aplikasi kami dan memasukkan data pelanggan baharu, pengecualian akan dijana dalam kelas DbModelBuilder disebabkan fakta bahawa ia tidak dapat membina model data entiti dengan betul. (Izinkan saya mengingatkan anda bahawa aplikasi kami ialah tapak ASP.NET yang mudah di mana keupayaan untuk memasukkan pelanggan baharu dilaksanakan.)

Pengecualian ini disebabkan oleh Rangka Kerja Entiti yang tidak menemui sifat bernama Id atau ProjectId dalam jadual Projek dan Code-First tidak dapat mengetahui medan yang hendak digunakan sebagai kunci utama jadual. Isu ini boleh dibetulkan dengan menggunakan anotasi data atau Fluent API, seperti yang ditunjukkan dalam contoh di bawah:

Projek kelas awam ( Public Guid Identifier ( get; set; ) public DateTime StartDate ( get; set; ) public DateTime EndDate ( get; set; ) public decimal Kos ( get; set; ) ) // sama dengan Fluent API protected override void OnModelCreating(DbModelBuilder modelBuilder) ( modelBuilder.Entity ().HasKey(p => p.Pengecam); )

Ambil perhatian bahawa apabila menggunakan API Fasih, kaedah HasKey() ditentukan selepas panggilan kaedah Entiti (), bukan selepas memanggil Entiti ().Property(), seperti yang dilakukan dalam contoh di atas, kerana Kunci utama ditetapkan pada peringkat jadual, bukan pada peringkat harta.

Menyediakan autokenaikan untuk kunci utama

Seperti yang dapat dilihat daripada jadual, mengikut konvensyen, Rangka Kerja Entiti menentukan kenaikan automatik untuk sifat jenis int. Dalam jadual Projek yang dibuat sebelum ini, jenis kunci utama ditentukan sebagai Panduan, akibatnya EF tidak menggunakan pembilang untuk medan ini semasa membuat jadual dalam pangkalan data. Ini ditunjukkan dalam rajah:

Mari tambahkan borang web baharu pada projek kami, yang akan kami panggil DatabaseGenerated.aspx. Dalam pengendali Page_Load, tambahkan kod berikut di mana kami menambah data baharu pada jadual Projek. Dalam kes ini, data ini akan ditambah apabila kami membuka halaman borang web kami dalam penyemak imbas.

Menggunakan Sistem; menggunakan System.Data.Entity; menggunakan CodeFirst; ruang nama ProfessorWeb.EntityFramework ( public partial class DatabaseGenerated: System.Web.UI.Page ( protected void Page_Load(penghantar objek, EventArgs e) ( // Tetapan ini diperlukan supaya pangkalan data secara automatik // dipadam dan dibuat semula apabila perubahan struktur model // (untuk memudahkan untuk menguji contoh) Pangkalan Data.SetInitializer(DropCreateDatabaseIfModelChanges baharu ()); Konteks SampleContext = new SampleContext(); projek projek= Projek baharu ( StartDate = DateTime.Now, EndDate = DateTime.Now.AddMonths(1), Cost = 8000M ); context.Projects.Add(projek); context.SaveChanges(); ) ) )

Jalankan projek dan buka borang web DatabaseGenerated.aspx. Akibatnya, rekod baharu akan ditambahkan pada jadual Projek:

Pangkalan data mahupun Rangka Kerja Entiti tidak mengetahui bahawa kami ingin mencipta Panduan baharu untuk setiap entri baharu, jadi Panduan yang mengandungi semua sifar akan dijana secara automatik. Jika anda memuat semula halaman dalam penyemak imbas (sebenarnya, dalam kes ini kod akan cuba memasukkan rekod baharu ke dalam jadual), maka Rangka Kerja Entiti akan mengembalikan SqlException, yang berlaku kerana kami cuba memasukkan rekod dengan pengecam yang telah wujud dalam jadual, iaitu e. dalam kes ini, kekangan kunci utama dicetuskan - ia mestilah unik untuk setiap rekod baharu.

Akibatnya, untuk menyelesaikan masalah ini, kami perlu menjana Panduan unik dalam kod. Jadual yang menggunakan autokenaikan untuk kunci utama tidak mempunyai ini kerja lebih, kerana Untuk setiap rekod baharu yang dimasukkan, pembilang mencipta nilai baharu untuk kunci utama dengan mendapatkan semula nilai kunci utama untuk rekod terakhir dan menambah 1 padanya (jika konstruk IDENTITY(1,1) digunakan).

Untuk menyelesaikan masalah ini untuk kunci jenis selain daripada int, anda perlu menggunakan atribut metadata DatabaseGenerated, dalam pembina yang anda tentukan Penghitungan DatabaseGeneratedOption, yang mempunyai tiga nilai yang mungkin:

tiada

Pangkalan data tidak mencipta sebarang nilai unik untuk kunci utama. Malah, dengan pilihan ini anda boleh melumpuhkan penambahan automatik kenaikan automatik kepada kunci utama jenis int.

identiti

Apabila anda memasukkan nilai ke dalam jadual, pangkalan data akan mencipta nilai unik untuk kunci utama.

Dikira

Sama seperti Identiti, dengan satu-satunya pengecualian bahawa kunci utama akan dijana bukan sahaja apabila memasukkan rekod ke dalam jadual, tetapi juga semasa mengemas kininya.

Ubah suai kelas model untuk mengarahkan pangkalan data mencipta kunci utama yang unik:

Projek kelas awam ( Pengecam Panduan awam ( get; set; ) public DateTime StartDate ( get; set; ) public DateTime EndDate ( get; set; ) public decimal Kos ( get; set; ) )

Jalankan projek sampel dan muat semula halaman beberapa kali untuk memasukkan beberapa rekod ke dalam jadual dan memastikan pengecualian tidak lagi dibuang. Imej di bawah menunjukkan data yang ditambahkan pada jadual:

Sila ambil perhatian ID yang dijana secara automatik untuk projek. Kesan yang sama boleh dicapai menggunakan kaedah HasDatabaseGeneratedOption() dalam Fluent API:

Dilindungi membatalkan OnModelCreating(DbModelBuilder modelBuilder) ( modelBuilder.Entity ().Property(p => p.Identifier).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); )

Bekerja dengan jenis data yang kompleks

Rangka Kerja Entiti telah menyokong keupayaan untuk menggunakan jenis kompleks sejak versi 1. Malah, jenis kompleks dalam .NET ialah kelas yang boleh dirujuk dalam kelas model. Jenis kompleks tidak mempunyai kunci dan boleh digunakan dalam berbilang objek model. Mari lihat contoh model berikut:

Pengguna kelas awam ( public int UserId ( get; set; ) public int SocialNumber ( get; set; ) rentetan awam FirstName ( get; set; ) rentetan awam Nama Akhir ( get; set; ) rentetan awam StreetAddress ( get; set; ) awam rentetan Bandar ( dapatkan; set; ) rentetan awam Kod Zip ( dapatkan; set; ) )

Dalam kelas ini, alamat kediaman pengguna boleh diasingkan ke dalam kelas yang berasingan dan dirujuk kepada:

Pengguna kelas awam ( public int UserId ( get; set; ) public int SocialNumber ( get; set; ) public string FirstName ( get; set; ) public string LastName ( get; set; ) public Address Address ( get; set; ) ) Alamat kelas awam ( public int AddressId ( get; set; ) rentetan awam StreetAddress ( dapatkan; set; ) rentetan awam Bandar ( dapatkan; set; ) rentetan awam Kod Zip ( dapatkan; set; ) )

Mengikut konvensyen, Rangka Kerja Entiti akan menghuraikan model ini sebagai dua jadual berasingan. Tetapi matlamat kami adalah untuk mencipta jenis kompleks daripada kelas Alamat. Cara tradisional untuk mencipta jenis kompleks daripada kelas Alamat adalah untuk mengalih keluar AddressId:

Alamat kelas awam ( // public int AddressId ( get; set; ) rentetan awam StreetAddress ( dapatkan; set; ) rentetan awam Bandar ( dapatkan; set; ) rentetan awam Kod Zip ( dapatkan; set; ) )

Sebagai tambahan kepada peraturan bahawa jenis kompleks tidak boleh mempunyai kunci, Code-First mengenakan dua peraturan lain yang mesti dipenuhi untuk mengesan jenis kompleks. Pertama, jenis kompleks mesti mengandungi hanya sifat mudah. Kedua, kelas yang menggunakan jenis ini tidak dibenarkan untuk menentukan jenis koleksi untuk sifat jenis kompleks. Dalam erti kata lain, jika anda ingin menggunakan alamat jenis kompleks dalam kelas Pengguna, maka harta yang mempunyai jenis itu tidak boleh ditandakan Senarai

atau gunakan koleksi lain.

Seperti yang ditunjukkan dalam rajah di bawah, selepas menjalankan aplikasi, Code-First mengenali jenis kompleks dan mencipta medan khas dalam jadual Pengguna (ingat untuk menambah pengisytiharan Pengguna dalam kelas konteks):

Perhatikan bagaimana medan yang menerangkan alamat pengguna dinamakan: ComplexTypeName_PropertyName. Ini ialah konvensyen Rangka Kerja Entiti untuk menamakan jenis kompleks.

Mengkonfigurasi Jenis Kompleks untuk Memintas Kod-Pertama Konvensyen

Bagaimana jika kelas anda yang menerangkan jenis kompleks tidak mengikut konvensyen Rangka Kerja Entiti, sebagai contoh, anda ingin menggunakan medan AddressId dalam kelas Alamat? Jika sekarang kita menambah medan ini ke kelas Alamat dan menjalankan projek, maka bukannya satu Jadual pengguna dan alamat jenis kompleks, Rangka Kerja Entiti akan mencipta dua jadual yang berkaitan antara satu sama lain kunci asing. Untuk menyelesaikan masalah ini, anda boleh nyatakan dengan jelas Atribut ComplexType dalam kelas model atau kegunaan Kaedah ComplexType(). Kelas DbModelBuilder dalam Fluent API:

Alamat kelas awam ( public int AddressId ( get; set; ) rentetan awam StreetAddress ( get; set; ) rentetan awam Bandar ( get; set; ) rentetan awam ZipCode ( get; set; ) ) // sama dengan Fluent API protected override void OnModelCreating(DbModelBuilder modelBuilder) ( modelBuilder.ComplexType

(); }

Dikatakan di atas bahawa kelas yang menerangkan jenis kompleks harus mempunyai sifat mudah sahaja (iaitu, kelas yang tidak merujuk kepada objek lain). Perjanjian ini boleh diatasi menggunakan cara yang sama. Di bawah ialah contoh di mana UserInfo jenis kompleks baharu telah ditambahkan yang merujuk kepada jenis Nama Penuh yang lain:

Pengguna kelas awam ( public int UserId ( get; set; ) public UserInfo UserInfo ( get; set; ) Alamat Alamat awam ( get; set; ) ) public class UserInfo ( public int SocialNumber ( get; set; ) // Bukan harta mudah public FullName Nama Penuh ( get; set; ) ) public class FullName ( public string FirstName ( get; set; ) public string LastName ( get; set; ) ) public class Address ( public int AddressId ( get; set; ) public string StreetAddress ( get; set; ) rentetan awam Bandar ( dapatkan; set; ) rentetan awam Kod Zip ( dapatkan; set; ) )

Dengan menyatakan kepada Code-First bahawa UserInfo ialah jenis kompleks menggunakan atribut ComplexType, kami mengatasi had yang dikenakan pada jenis kompleks menggunakan konvensyen lalai.

Perlu diingat bahawa Code-First membolehkan anda menyesuaikan jenis kompleks seperti jadual biasa menggunakan API Fluent atau anotasi. Di bawah ialah contoh untuk menyediakan jenis Alamat yang kompleks:

Alamat kelas awam ( public int AddressId ( get; set; ) rentetan awam StreetAddress ( get; set; ) rentetan awam Bandar ( get; set; ) rentetan awam ZipCode ( get; set; ) ) // sama dengan Fluent API protected override void OnModelCreating(DbModelBuilder modelBuilder) ( modelBuilder.ComplexType

().Property(a => a.StreetAddress).HasMaxLength(100); )

Rajah di bawah menunjukkan struktur jadual Pengguna. Di sini anda boleh melihat cara EF menamakan sifat jenis kompleks dengan rujukan di dalamnya dan EF meletakkan kekangan pada medan StreetAddress:

Perihalan tetapan lain

Dalam bahagian ini, kami akan melihat secara ringkas semua tetapan lajur jadual yang tinggal, yang digunakan agak jarang disebabkan ciri khusus mereka.

Lajur cap masa

Jenis data T-SQL TIMESTAMP menentukan lajur yang ditakrifkan sebagai VARBINAR(8) atau BINARI(8), bergantung pada kebolehtebalan lajur. Untuk setiap pangkalan data, sistem mengekalkan pembilang yang bertambah setiap kali mana-mana baris yang mengandungi sel TIMESTAMP dimasukkan atau dikemas kini dan memberikan nilai itu kepada sel tersebut. Oleh itu, menggunakan sel TIMESTAMP, anda boleh menentukan masa relatif pengubahsuaian terakhir baris jadual yang sepadan. (ROWVERSION ialah sinonim untuk TIMESTAMP.)

Dengan sendirinya, nilai yang disimpan dalam lajur TIMESTAMP tidak penting. Lajur ini biasanya digunakan untuk menentukan sama ada rentetan tertentu jadual sejak kali terakhir ia diakses. Ini membolehkan akses serentak ke jadual pangkalan data ditangani dengan membenarkan utas lain menyekat jika utas semasa telah menukar nilai berturut-turut.

Dalam Code-First, untuk menunjukkan bahawa lajur hendaklah daripada jenis TIMESTAMP, nama yang sama mesti digunakan Atribut cap masa dalam anotasi atau IsRowVersion() kaedah dalam Fluent API, seperti yang ditunjukkan dalam contoh di bawah:

RowVersion byte awam ( get; set; ) // sama dengan Fluent API protected override void OnModelCreating(DbModelBuilder modelBuilder) ( modelBuilder.Entity ().Property(p => p.RowVersion).IsRowVersion(); )

Cara yang kurang biasa untuk memastikan keselamatan apabila bekerja dengan urutan serentak adalah dengan menentukan semakan serentak untuk setiap lajur. Kaedah ini juga boleh digunakan dalam DBMS yang tidak menyokong jenis Cap Waktu/Rowversion. Apabila beroperasi dengan cara ini, benang tidak menyemak sama ada rekod dalam jadual telah berubah, tetapi hanya menyekat akses kepadanya untuk urutan lain sehingga ia melengkapkan proses penulisan. Untuk menentukan lajur yang harus lulus semakan serentak, gunakan Atribut ConcurrencyCheck dalam anotasi, atau Kaedah IsConcurrencyToken(). dalam Fluent API.

Menukar pengekodan rentetan daripada Unicode kepada ASCII

Secara lalai Rangka Kerja Entiti menukar segala-galanya jenis rentetan model data seperti rentetan atau char ke dalam jenis rentetan data SQL, menggunakan pengekodan Unicode dua bait - NVARCHAR atau NCHAR. Anda boleh menukar tingkah laku ini dan secara jelas memberitahu EF untuk menggunakan bait tunggal Pengekodan ASCII– Jenis VARCHAR dan CHAR akan digunakan dengan sewajarnya. Untuk melakukan ini, anda perlu menggunakan Kaedah IsUnicode(). dengan parameter boolean yang dihantar kepadanya palsu dalam Fluent API. Anotasi tidak menyediakan keupayaan untuk menyesuaikan pengekodan rentetan.

Menentukan ketepatan untuk jenis Perpuluhan

Untuk menentukan ketepatan bagi jenis Perpuluhan (bilangan digit dalam nombor) dan skala (bilangan digit di sebelah kanan titik perpuluhan dalam bilangan) boleh digunakan kaedah HasPrecision(). dengan menghantar dua parameter kepadanya, yang digunakan dalam Fluent API. Anotasi data dalam Code-First tidak menawarkan alternatif kepada kaedah ini. Secara lalai, Rangka Kerja Entiti menetapkan ketepatan kepada 18 dan skala kepada 2 untuk jenis Perpuluhan.

Contoh di bawah menunjukkan penggunaan kaedah ini, untuk sifat Kos jadual Projek yang kami buat sebelum ini, apabila melihat kunci utama:

Dilindungi membatalkan OnModelCreating(DbModelBuilder modelBuilder) ( modelBuilder.Entity ().Harta(p => p.Kos).HasPrecision(6, 3); )

Menunjukkan bahawa lajur baharu ialah lajur identiti. Apabila ditambahkan pada jadual baris baru Enjin pangkalan data menjana nilai jujukan unik untuk lajur ini. Lajur pengecam biasanya digunakan dengan kekangan PRIMARY KEY untuk mengekalkan keunikan pengecam baris dalam jadual. Sifat IDENTITY boleh diberikan kepada lajur jenis tinyint, smallint, int, bigint, perpuluhan(p,0) atau numeric(p,0). Anda hanya boleh membuat satu lajur identiti bagi setiap jadual. Nilai lalai tidak boleh digunakan dalam lajur identiti. Anda mesti menentukan kedua-dua nilai awal dan kenaikan, atau anda tidak boleh menentukan apa-apa. Jika tiada nilai dinyatakan, nilai lalai ialah (1,1).

Sintaks:

[ IDENTITI [ (benih, kenaikan) ]

seed- nilai yang digunakan untuk baris pertama dimuatkan ke dalam jadual.

ipenambahan - s Nilai kenaikan ditambahkan pada nilai ID baris yang dimuatkan sebelum ini.

[ Kad masa nombor] IDENTITI INT (1, 1) BUKAN NULL KUNCI UTAMA

    Medan yang dikira.

Sintaks:

<имя_столбца> AS <выражение> ]

Ungkapan yang menentukan nilai lajur yang dikira. Lajur yang dikira ialah lajur maya yang tidak disimpan secara fizikal dalam jadual melainkan ia BERKEKAL. Nilai lajur dikira berdasarkan ungkapan yang menggunakan lajur lain dalam jadual yang sama.

Sebagai contoh, takrifan lajur yang dikira mungkin:

Kos barangan AS Harga untuk satu * Kuantiti.

Ungkapan ini boleh menjadi nama lajur yang tidak dikira, pemalar, fungsi, pembolehubah atau mana-mana gabungan ini, disambungkan oleh satu atau lebih pengendali. Ungkapan itu tidak boleh menjadi subkueri atau mengandungi alias jenis data.

Lajur yang dikira boleh digunakan dalam senarai pilihan, klausa WHERE, klausa ORDER BY dan mana-mana tempat lain yang menggunakan ungkapan biasa, kecuali dalam kes berikut.

Lajur yang dikira tidak boleh digunakan sebagai definisi sekatan lalai atau KUNCI ASING, mahupun bersamaan dengan takrif kekangan NOT NULL. Walau bagaimanapun, lajur yang dikira boleh digunakan sebagai lajur kunci indeks atau sebagai sebahagian daripada beberapa KUNCI UTAMA atau kekangan UNIK jika nilai lajur yang dikira itu ditentukan oleh ungkapan deterministik (boleh diramal) dan jenis data hasil dibenarkan dalam lajur indeks .

Contohnya, jika jadual mengandungi lajur integer a Dan b, lajur dikira a+b boleh dimasukkan ke dalam indeks, dan lajur yang dikira a+DATEPART(dd, GETDATE())- tidak boleh, kerana nilainya mungkin berubah dalam panggilan berikutnya.

Lajur yang dikira tidak boleh menjadi lajur sasaran bagi pernyataan INSERT atau UPDATE.

DBMS secara automatik menentukan sama ada lajur yang dikira boleh NULLable berdasarkan ungkapan yang digunakan. Hasil daripada kebanyakan ungkapan dianggap boleh dibatalkan, walaupun hanya lajur tidak boleh dibatalkan digunakan, kerana kemungkinan limpahan atau ketidaktepatan boleh menghasilkan nilai nol. Untuk menentukan sama ada lajur jadual yang dikira boleh menjadi NULL, gunakan fungsi COLUMNPROPERTY dengan sifat MembolehkanNull. Anda boleh membuat ungkapan tidak boleh dibatalkan dengan menentukan ISNULL dengan pemalar semak_ungkapan, dengan pemalar ialah nilai bukan nol yang menggantikan sebarang nilai NULL. Lajur yang dikira berdasarkan ungkapan yang mengandungi jenis yang ditentukan pengguna CLR memerlukan kebenaran jenis RUJUKAN.

Menentukan bahawa SQL Server akan menyimpan secara fizikal nilai yang dikira dalam jadual dan mengemas kininya apabila mana-mana lajur yang bergantung kepada lajur yang dikira berubah. Menentukan PERSISTED pada lajur yang dikira membolehkan anda membuat indeks pada lajur terkira yang bersifat deterministik tetapi tidak tepat.

Pada mencipta jadual Sebagai tambahan kepada teknik yang dibincangkan di atas, anda boleh menentukan kata kunci CONSTRAINT pilihan untuk memberikan kekangan nama yang unik dalam pangkalan data.

CIPTA T MAMPU Pesanan(

ID_PesananINT BUKAN NULL ,

Hidangan INT BUKAN NULL,

Kuantiti_ hidangan INT BUKAN NULL CHECK( Kuantiti_ hidangan >0 ) ,

Tarikh TARIKH BUKAN NULL ,

KUNCI UTAMA( ID_Pesanan, Hidangan, Tarikh),

KEKANGAN KUNCI ASING

KUNCI ASING ( Hidangan, Tarikh) RUJUKAN Menu( Hidangan, Tarikh)) ;

Kemudian anda boleh bekerja dengan kekangan bernama seperti dengan objek pangkalan data. Jika nama kekangan tidak dinyatakan, kernel SUDB akan menciptanya secara automatik, memilih nama mengikut peraturan yang ditakrifkan dalam sistem.

Contoh skrip yang dibina oleh sistem untuk mencipta jadual Catalog_type_of_dish

BUAT JADUAL .[Direktori_jenis_hidangan](

IDENTITI(1,1) BUKAN NULL,

[Lihat] (20) BUKAN NULL,

KEKANGAN UTAMA UTAMA BERKUMPUL

) DENGAN (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON