Vp.FSharp.Sqlห้องสมุดหลักที่ช่วยให้คุณสามารถทำงานกับ F# และผู้ให้บริการ ADO ใด ๆ ได้อย่างต่อเนื่อง
ในกรณีส่วนใหญ่ห้องสมุดนี้ใช้สำหรับการสร้างห้องสมุด F# อื่น ๆ ที่ใช้ประโยชน์จากผู้ให้บริการ ADO ที่เกี่ยวข้องเท่านั้น
หากคุณต้องการเรียกใช้คำสั่ง SQL คำสั่ง A-LA-F#คุณอาจต้องการดูส่วนนี้
เราติดตาม "การปฏิบัติที่ถกเถียงกันอย่างมาก" เพื่อความสามารถที่ดีที่สุดของเรา!
| สถานะ | บรรจุุภัณฑ์ |
|---|---|
| ตกลง | |
| ตกลง (sorta) | |
| TBD | |
| TBD |
| ชื่อ | รุ่น | สั่งการ |
|---|---|---|
Vp.FSharp.Sql | Install-Package Vp.FSharp.Sql |
ห้องสมุดนี้ส่วนใหญ่มีจุดมุ่งหมายที่จะเป็นรากฐานสำหรับการสร้างห้องสมุดอื่น ๆ ที่มีผู้ให้บริการ ADO.NET ที่เกี่ยวข้องเพื่อมอบประสบการณ์ที่พิมพ์อย่างเข้มงวด
คุณสามารถตรวจสอบไลบรารีด้านล่างแต่ละ Leperaging Vp.FSharp.Sql และผู้ให้บริการ ADO.NET ที่เกี่ยวข้อง:
| ชื่อ | ผู้ให้บริการ ado.net | รุ่น | สั่งการ |
|---|---|---|---|
Vp.FSharp.Sql.Sqlite | System.Data.SQLite.Core | Install-Package Vp.FSharp.Sql.Sqlite | |
Vp.FSharp.Sql.SqlServer | Microsoft.Data.SqlClient | Install-Package Vp.FSharp.Sql.SqlServer | |
Vp.FSharp.Sql.PostgreSql | Npgsql | Install-Package Vp.FSharp.Sql.PostgreSql |
สรุปคุณสามารถสร้างผู้ให้บริการที่สมบูรณ์ของคุณเอง แต่คุณมีอิสระที่จะไปกับสิ่งที่คุณต้องการเท่านั้น
มาเดินผ่าน Vp.FSharp.Sql.Sqlite Provider Provider
ก่อนอื่นคุณต้องมีประเภทที่สำคัญที่สุดของทั้งหมดประเภทของฐานข้อมูล
ในกรณีของ sqlite SqliteDbValue สามารถสร้างแบบจำลองเป็นสหภาพที่เลือกปฏิบัติอย่างง่าย (DU):
/// Native SQLite DB types.
/// See https://www.sqlite.org/datatype3.html
type SqliteDbValue =
| Null
| Integer of int64
| Real of double
| Text of string
| Blob of byte arrayแหล่งข้อมูลตัวอย่าง จุดยึด
กรณีเหล่านี้ถูกสร้างขึ้นหลังจากเอกสาร SQLite อย่างเป็นทางการ
นี่คือที่ที่เราแปลง DU ที่เปิดเผยใน API สาธารณะเป็นคลาส DbParameter ที่เข้ากันได้จริงที่สามารถใช้งานได้จากฟังก์ชั่นห้องสมุดหลัก
ในสถานการณ์ส่วนใหญ่การใช้งานประกอบด้วยรูปแบบการเขียนตรงกับกรณีประเภทของฐานข้อมูลที่แตกต่างกันและสร้างประเภทเฉพาะ DbParameter ที่เกี่ยวข้องที่มีอยู่ในผู้ให้บริการ ADO.NET ถ้ามี:
let dbValueToParameter name value =
let parameter = SQLiteParameter ()
parameter.ParameterName <- name
match value with
| Null ->
parameter.TypeName <- ( nameof Null ) .ToUpperInvariant ()
| Integer value ->
parameter.TypeName <- ( nameof Integer ) .ToUpperInvariant ()
parameter.Value <- value
| Real value ->
parameter.TypeName <- ( nameof Real ) .ToUpperInvariant ()
parameter.Value <- value
| Text value ->
parameter.TypeName <- ( nameof Text ) .ToUpperInvariant ()
parameter.Value <- value
| Blob value ->
parameter.TypeName <- ( nameof Blob ) .ToUpperInvariant ()
parameter.Value <- value
parameterหมายเหตุ: ฟังก์ชั่นนี้ไม่จำเป็นต้องเปิดเผยต่อสาธารณะเฉพาะ DU เท่านั้นที่จะต้องเปิดเผยต่อสาธารณะ
SqlDependencies ทำหน้าที่เหมือนกาวที่ยึดติดกับการดำเนินการเฉพาะ ADO ที่สำคัญที่สุดทั้งหมด:
/// SQLite Dependencies
type SqliteDependencies =
SqlDependencies <
SQLiteConnection ,
SQLiteCommand ,
SQLiteParameter ,
SQLiteDataReader ,
SQLiteTransaction ,
SqliteDbValue >อินสแตนซ์ของประเภทนี้สามารถนำไปใช้กับ:
let beginTransactionAsync ( connection : SQLiteConnection ) ( isolationLevel : IsolationLevel ) _ =
ValueTask.FromResult ( connection.BeginTransaction ( isolationLevel ))
let executeReaderAsync ( command : SQLiteCommand ) _ =
Task.FromResult ( command.ExecuteReader ())
{ CreateCommand = fun connection -> connection.CreateCommand ()
SetCommandTransaction = fun command transaction -> command.Transaction <- transaction
BeginTransaction = fun connection -> connection.BeginTransaction
BeginTransactionAsync = beginTransactionAsync
ExecuteReader = fun command -> command.ExecuteReader ()
ExecuteReaderAsync = executeReaderAsync
DbValueToParameter = Constants.DbValueToParameter } ในกรณีนี้โดยเฉพาะ System.Data.SQLite ประเภทที่เฉพาะเจาะจงมากที่สุดมีให้เฉพาะผ่าน API ที่ไม่ใช่ asynchronous
ตัวอย่างเช่นเราใช้ command.ExecuteReader แทน command.ExecuteDbDataReader เนื่องจากประเภทการส่งคืนเป็นประเภทที่เฉพาะเจาะจงที่สุด:
SQLiteCommand.ExecuteDbDataReader()SQLiteCommand.ExecuteReader()นอกจากนี้ในขณะที่คุณอาจสังเกตเห็นว่าไม่มีการเกิดขึ้นของ API แบบอะซิงโครนัสซึ่งหมายความว่าการใช้งานแบบอะซิงโครนัส
DbCommand.ExecuteReaderAsync()DbCommand.ExecuteDbDataReader(CommandBehavior behavior)ซึ่งเป็นเพียงเสื้อคลุมแบบอะซิงโครนัสรอบรุ่นซิงโครนัส
ในทำนองเดียวกันเมื่อมันมาถึง connection.BeginTransaction แทน command.BeginTransactionAsync :
SQLiteConnection.BeginTransaction()DbConnection.BeginTransactionAsync()ตัวอย่างนี้เพียงอย่างเดียวแสดงให้เห็นถึงความแตกต่างที่คุณคาดหวังว่าจะพบในการใช้งาน ADO.NET ผู้ให้บริการที่มีอยู่มากที่สุด
เพื่อความเรียบง่ายคุณสามารถ จำกัด ประเภท CommandDefinition ด้วยประเภทผู้ให้บริการ ADO ที่เกี่ยวข้องเป็นประเภทของสารยึดเกาะ:
/// SQLite Command Definition
type SqliteCommandDefinition =
CommandDefinition <
SQLiteConnection ,
SQLiteCommand ,
SQLiteParameter ,
SQLiteDataReader ,
SQLiteTransaction ,
SqliteDbValue > สิ่งนี้สามารถใช้งานได้ในภายหลังกับฟังก์ชั่น SqlCommand ซึ่งยอมรับ CommandDefinition เป็นหนึ่งในพารามิเตอร์ของพวกเขา
ยังมีความเชี่ยวชาญอื่นในแง่ของข้อ จำกัด ทั่วไป:
/// SQLite Configuration
type SqliteConfiguration =
SqlConfigurationCache <
SQLiteConnection ,
SQLiteCommand >ประเภทนี้เป็นสารยึดเกาะอื่นสำหรับประเภทและทำหน้าที่เป็นแคช มันจะถูกส่งผ่านไปพร้อมกับคำจำกัดความของคำสั่งเมื่อดำเนินการคำสั่ง
สิ่งนี้ค่อนข้างตรงไปตรงมาสิ่งที่คุณต้องทำคือ:
SqlCommand [<RequireQualifiedAccess>]
module Vp.FSharp.Sql.Sqlite.SqliteCommand
open Vp. FSharp . Sql
/// Initialize a new command definition with the given text contained in the given string.
let text value : SqliteCommandDefinition =
SqlCommand.text value
/// Initialize a new command definition with the given text spanning over several strings (ie. list).
let textFromList value : SqliteCommandDefinition =
SqlCommand.textFromList value
/// Update the command definition so that when executing the command, it doesn't use any logger.
/// Be it the default one (Global, if any.) or a previously overriden one.
let noLogger commandDefinition = { commandDefinition with Logger = LoggerKind.Nothing }
/// Update the command definition so that when executing the command, it use the given overriding logger.
/// instead of the default one, aka the Global logger, if any.
let overrideLogger value commandDefinition = { commandDefinition with Logger = LoggerKind.Override value }
/// Update the command definition with the given parameters.
let parameters value ( commandDefinition : SqliteCommandDefinition ) : SqliteCommandDefinition =
SqlCommand.parameters value commandDefinition
/// Update the command definition with the given cancellation token.
let cancellationToken value ( commandDefinition : SqliteCommandDefinition ) : SqliteCommandDefinition =
SqlCommand.cancellationToken value commandDefinition
/// Update the command definition with the given timeout.
/// Note: kludged because SQLite doesn't support per-command timeout values.
let timeout value ( commandDefinition : SqliteCommandDefinition ) : SqliteCommandDefinition =
SqlCommand.timeout value commandDefinition
/// Update the command definition and sets whether the command should be prepared or not.
let prepare value ( commandDefinition : SqliteCommandDefinition ) : SqliteCommandDefinition =
SqlCommand.prepare value commandDefinition
/// Update the command definition and sets whether the command should be wrapped in the given transaction.
let transaction value ( commandDefinition : SqliteCommandDefinition ) : SqliteCommandDefinition =
SqlCommand.transaction value commandDefinitionในทำนองเดียวกันการดำเนินการคำสั่งเป็นไปตามหลักการเดียวกัน AKA ผ่านพารามิเตอร์ประเภทที่เกี่ยวข้อง (สอดคล้องกับผู้ให้บริการ ADO.NET ปัจจุบันและเฉพาะของคุณ) ไปยังฟังก์ชั่นหลักของ SQLCommand
/// Execute the command and return the sets of rows as an AsyncSeq accordingly to the command definition.
/// This function runs asynchronously.
let queryAsyncSeq connection read ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.queryAsyncSeq
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read commandDefinition
/// Execute the command and return the sets of rows as an AsyncSeq accordingly to the command definition.
/// This function runs synchronously.
let querySeqSync connection read ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.querySeqSync
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read commandDefinition
/// Execute the command and return the sets of rows as a list accordingly to the command definition.
/// This function runs asynchronously.
let queryList connection read ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.queryList
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read commandDefinition
/// Execute the command and return the sets of rows as a list accordingly to the command definition.
/// This function runs synchronously.
let queryListSync connection read ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.queryListSync
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read commandDefinition
/// Execute the command and return the first set of rows as a list accordingly to the command definition.
/// This function runs asynchronously.
let querySetList connection read ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.querySetList
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read commandDefinition
/// Execute the command and return the first set of rows as a list accordingly to the command definition.
/// This function runs synchronously.
let querySetListSync connection read ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.querySetListSync
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read commandDefinition
/// Execute the command and return the 2 first sets of rows as a tuple of 2 lists accordingly to the command definition.
/// This function runs asynchronously.
let querySetList2 connection read1 read2 ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.querySetList2
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read1 read2 commandDefinition
/// Execute the command and return the 2 first sets of rows as a tuple of 2 lists accordingly to the command definition.
/// This function runs synchronously.
let querySetList2Sync connection read1 read2 ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.querySetList2Sync
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read1 read2 commandDefinition
/// Execute the command and return the 3 first sets of rows as a tuple of 3 lists accordingly to the command definition.
/// This function runs asynchronously.
let querySetList3 connection read1 read2 read3 ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.querySetList3
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read1 read2 read3 commandDefinition
/// Execute the command and return the 3 first sets of rows as a tuple of 3 lists accordingly to the command definition.
/// This function runs synchronously.
let querySetList3Sync connection read1 read2 read3 ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.querySetList3Sync
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) read1 read2 read3 commandDefinition
/// Execute the command accordingly to its definition and,
/// - return the first cell value, if it is available and of the given type.
/// - throw an exception, otherwise.
/// This function runs asynchronously.
let executeScalar < 'Scalar > connection ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.executeScalar < 'Scalar , _, _, _, _, _, _, _, _>
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) commandDefinition
/// Execute the command accordingly to its definition and,
/// - return the first cell value, if it is available and of the given type.
/// - throw an exception, otherwise.
/// This function runs synchronously.
let executeScalarSync < 'Scalar > connection ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.executeScalarSync < 'Scalar , _, _, _, _, _, _, _, _>
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) commandDefinition
/// Execute the command accordingly to its definition and,
/// - return Some, if the first cell is available and of the given type.
/// - return None, if first cell is DBNull.
/// - throw an exception, otherwise.
/// This function runs asynchronously.
let executeScalarOrNone < 'Scalar > connection ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.executeScalarOrNone < 'Scalar , _, _, _, _, _, _, _, _>
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) commandDefinition
/// Execute the command accordingly to its definition and,
/// - return Some, if the first cell is available and of the given type.
/// - return None, if first cell is DBNull.
/// - throw an exception, otherwise.
/// This function runs synchronously.
let executeScalarOrNoneSync < 'Scalar > connection ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.executeScalarOrNoneSync < 'Scalar , _, _, _, _, _, _, _, _>
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) commandDefinition
/// Execute the command accordingly to its definition and, return the number of rows affected.
/// This function runs asynchronously.
let executeNonQuery connection ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.executeNonQuery
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) commandDefinition
/// Execute the command accordingly to its definition and, return the number of rows affected.
/// This function runs synchronously.
let executeNonQuerySync connection ( commandDefinition : SqliteCommandDefinition ) =
SqlCommand.executeNonQuerySync
connection ( Constants.Deps ) ( SqliteConfiguration.Snapshot ) commandDefinitionเราสามารถสร้างโมดูลอื่นสำหรับผู้ช่วยที่ว่างเปล่าและส่วนที่เหลือคือทั้งหมดที่เกี่ยวกับการส่งผ่านพารามิเตอร์ที่เกี่ยวข้องไปยังฟังก์ชั่นหลักพื้นฐาน
[<RequireQualifiedAccess>]
module Vp.FSharp.Sql.Sqlite.SqliteNullDbValue
open Vp. FSharp . Sql
/// Return SQLite DB Null value if the given option is None, otherwise the underlying wrapped in Some.
let ifNone toDbValue = NullDbValue.ifNone toDbValue SqliteDbValue.Null
/// Return SQLite DB Null value if the option is Error, otherwise the underlying wrapped in Ok.
let ifError toDbValue = NullDbValue.ifError toDbValue ( fun _ -> SqliteDbValue.Null ) ที่นี่มากขึ้นที่นี่ด้วย
[<RequireQualifiedAccess>]
module Vp.FSharp.Sql.Sqlite.SqliteTransaction
open Vp. FSharp . Sql
open Vp. FSharp . Sql . Sqlite
let private beginTransactionAsync = Constants.Deps.BeginTransactionAsync
let private beginTransaction = Constants.Deps.BeginTransaction
/// Create and commit an automatically generated transaction with the given connection, isolation,
/// cancellation token and transaction body.
/// This function runs asynchronously.
let commit cancellationToken isolationLevel connection body =
Transaction.commit cancellationToken isolationLevel connection beginTransactionAsync body
/// Create and commit an automatically generated transaction with the given connection, isolation,
/// and transaction body.
/// This function runs synchronously.
let commitSync isolationLevel connection body =
Transaction.commitSync isolationLevel connection beginTransaction body
/// Create and do not commit an automatically generated transaction with the given connection, isolation,
/// cancellation token and transaction body.
/// This function runs asynchronously.
let notCommit cancellationToken isolationLevel connection body =
Transaction.notCommit cancellationToken isolationLevel connection beginTransactionAsync body
/// Create and do not commit an automatically generated transaction with the given connection, isolation,
/// and transaction body.
/// This function runs synchronously.
let notCommitSync isolationLevel connection body =
Transaction.notCommitSync isolationLevel connection beginTransaction body
/// Create and commit an automatically generated transaction with the given connection, isolation,
/// cancellation token and transaction body.
/// The commit phase only occurs if the transaction body returns Some.
/// This function runs asynchronously.
let commitOnSome cancellationToken isolationLevel connection body =
Transaction.commitOnSome cancellationToken isolationLevel connection beginTransactionAsync body
/// Create and commit an automatically generated transaction with the given connection, isolation,
/// and transaction body.
/// The commit phase only occurs if the transaction body returns Some.
/// This function runs synchronously.
let commitOnSomeSync isolationLevel connection body =
Transaction.commitOnSomeSync isolationLevel connection beginTransaction body
/// Create and commit an automatically generated transaction with the given connection, isolation,
/// cancellation token and transaction body.
/// The commit phase only occurs if the transaction body returns Ok.
/// This function runs asynchronously.
let commitOnOk cancellationToken isolationLevel connection body =
Transaction.commitOnOk cancellationToken isolationLevel connection beginTransactionAsync body
/// Create and commit an automatically generated transaction with the given connection, isolation,
/// and transaction body.
/// The commit phase only occurs if the transaction body returns Ok.
/// This function runs synchronously.
let commitOnOkSync isolationLevel connection body =
Transaction.commitOnOkSync isolationLevel connection beginTransaction body
/// Create and commit an automatically generated transaction with the given connection and transaction body.
/// This function runs asynchronously.
let defaultCommit connection body = Transaction.defaultCommit connection beginTransactionAsync body
/// Create and commit an automatically generated transaction with the given connection and transaction body.
/// This function runs synchronously.
let defaultCommitSync connection body = Transaction.defaultCommitSync connection beginTransaction body
/// Create and do not commit an automatically generated transaction with the given connection and transaction body.
/// This function runs asynchronously.
let defaultNotCommit connection body = Transaction.defaultNotCommit connection beginTransactionAsync body
/// Create and do not commit an automatically generated transaction with the given connection and transaction body.
/// This function runs synchronously.
let defaultNotCommitSync connection body = Transaction.defaultNotCommitSync connection beginTransaction body
/// Create and commit an automatically generated transaction with the given connection and transaction body.
/// The commit phase only occurs if the transaction body returns Ok.
/// This function runs asynchronously.
let defaultCommitOnSome connection body = Transaction.defaultCommitOnSome connection beginTransactionAsync body
/// Create and commit an automatically generated transaction with the given connection and transaction body.
/// The commit phase only occurs if the transaction body returns Ok.
/// This function runs synchronously.
let defaultCommitOnSomeSync connection body = Transaction.defaultCommitOnSomeSync connection beginTransaction body
/// Create and commit an automatically generated transaction with the given connection and transaction body.
/// The commit phase only occurs if the transaction body returns Some.
/// This function runs asynchronously.
let defaultCommitOnOk connection body = Transaction.defaultCommitOnOk connection beginTransactionAsync body
/// Create and commit an automatically generated transaction with the given connection and transaction body.
/// The commit phase only occurs if the transaction body returns Some.
/// This function runs synchronously.
let defaultCommitOnOkSync connection body = Transaction.defaultCommitOnOkSync connection beginTransaction bodyและ voila! ตอนนี้คุณทั้งหมดตัดสินและพร้อมที่จะดำเนินการคำสั่ง Wildest กับฐานข้อมูลที่คุณชื่นชอบ!
TransactionScope ผู้ช่วย ผู้ช่วยเหล่านี้ทำงานโดยไม่คำนึงถึงผู้ให้บริการ ADO.NET ที่คุณใช้ตราบเท่าที่รองรับ TransactionScope
ที่ถูกกล่าวว่า เราไม่สนับสนุนคุณจากการใช้ผู้ช่วยเหล่านั้น :
TransactionScope (ที่มีหรือไม่มีผู้ช่วยเหล่านั้น) เป็นข้อผิดพลาดได้ง่ายมากและคุณอาจพบพฤติกรรมที่ไม่คาดคิดโดยไม่มีข้อความแสดงข้อผิดพลาดที่ชัดเจนTransactionScope โดยไม่ต้องสนับสนุนการทำธุรกรรมแบบกระจายผู้ช่วยเหล่านั้นอาจย้ายไปที่ห้องสมุดแยกต่างหากหากคุณต้องการวิธีแก้ปัญหาที่ทำงานได้ถึง 2PC หรือการทำธุรกรรมแบบกระจายคุณอาจต้องการตรวจสอบรูปแบบสถาปัตยกรรมบางอย่างเช่นรูปแบบ SAGA
รายงานข้อผิดพลาดคำขอคุณสมบัติและคำขอดึงยินดีต้อนรับมาก!
โปรดอ่านแนวทางการบริจาคเพื่อเริ่มต้น
โครงการได้รับใบอนุญาตภายใต้ MIT
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับใบอนุญาตโปรดดูไฟล์ใบอนุญาต