İzlenecek yol: tipi sağlayıcıları (F#) kullanarak bir sql veritabanına erişme
Bu izlenecek yol; veritabanına bir canlı bağlantı varsa, veri türlerini SQL veritabanında F# 3.0 içinde oluşturmak için kullanılabilir SqlDataConnection (LINQ için SQL) tür sağlayıcısının nasıl kullanılacağını açıklar. Veritabanına canlı bir bağlantınız yoksa, ancak LINQ ile SQL arasında şema dosyası (DBML dosyası) varsa, bkz: İzlenecek yol: F# türleriyle dbml dosyasından (F#) oluşturma.
Bu izlenecek yol aşağıdaki görevleri gösterir. Bu görevlerin başarılı olması için izlenecek yol bu sırada gerçekleşmelidir:
Sınama Veritabanı Hazırlama
Projeyi oluşturma
Tür sağlayıcısını kurmak
Veriyi sorgulama
Null yapılabilir alanlar ile çalışma
Bir saklı yordamı çağırma
Veritabanını güncelleme
Transact-SQL kodunu yürütme
Tam veri içeriğini kullanma
Verileri silme
Sınama veritabanı oluşturma
Sınama Veritabanı Hazırlama
SQL Server çalıştıran bir sunucu üzerinde sınama amacıyla bir veritabanı oluşturun. Bir Sınama veritabanı oluşturma yapmak için bu sayfanın altındaki veritabanını oluşturma komut dosyasını kullanabilirsiniz.
Sınama Veritabanı Hazırlamak için
- Bir Sınama veritabanı oluşturma çalıştırmak için, Görüntüle menüsü açın ve SQL Server Nesne Gezgini veya Ctrl+\, Ctrl+S anahtarlarını seçin. Bir SQL Server Nesne Gezgini penceresinde, uygun örnek için kısayol menüsünü açın, Yeni Sorgu seçin, bu sayfanın altındaki komut dosyasını kopyalayın ve sonra komut dosyasını düzenleyiciye yapıştırın. SQL komut dosyasını çalıştırmak için üçgen simgesiyle araç çubuğunu seçin ya da Ctrl+Q anahtarlarını seçin. Bir SQL Server Nesne Gezgini hakkında daha fazla bilgi için bkz. Bağlı Veritabanı Gelişti
Projeyi oluşturma
Sonra, bir F# uygulama projesi oluşturun.
Projeyi oluşturmak ve kurmak için
Yeni bir F# Uygulama projesi oluşturun.
Başvuruları .FSharp.Data.TypeProviders, System.Data gibi, ve System.Data.Linq ekleyin .
Aşağıdaki kod satırlarını F# kod dosyası, Program.fs üstüne ekleyerek uygun ad alanlarını açın.
open System open System.Data open System.Data.Linq open Microsoft.FSharp.Data.TypeProviders open Microsoft.FSharp.Linq
Çoğu F# programlarında olduğu gibi, derlenmiş bir program olarak buradaki örneklerde kod yürütebilir veya bir komut dosyası olarak etkileşimli olarak çalıştırabilirsiniz. Komut dosyalarını kullanmak isterseniz, proje düğümü için kısayol menüsünü açın, Yeni Öğe Ekle seçin, bir F# komut dosyası ekleyin ve her adım için komut dosyası kodu ekleyin. Derleme başvurularını yüklemek için dosyanın en üstündeki sonraki satırları eklemeniz gerekecektir.
#r "System.Data.dll" #r "FSharp.Data.TypeProviders.dll" #r "System.Data.Linq.dll"
Daha sonra, ekledikçe her kod bloğunu seçebilirsiniz ve F# etkileşimli çalıştırmak için Alt+Enter basın.
Tür sağlayıcısını kurmak
Bu adımda, veritabanı şeması için bir tür sağlayıcısı oluşturun.
Doğrudan veritabanı bağlantısı üzerinden tür sağlayıcısını kurmak için
Tür sağlayıcısını kullanarak SQL veritabanını sıralamak için kullanabileceğiniz türleri oluşturmak için iki önemli kod satırı vardır. İlk olarak, tür sağlayıcını başlatın. Bunu yapmak için , bir SqlDataConnection için statik genel parametre ile benzer tür oluşturun. SqlDataConnection SQL türü sağlayıcısıdır ve ADO.NET programlamada kullanılan SqlConnection türü ile karıştırılmamalıdır. Bağlanmak istediğiniz veritabanı ve bağlantı dizesi varsa, aşağıdaki kodu tür sağlayıcısını çağırmak için kullanın. Verilen örnek dize için kendi bağlantı dizinize değiştirin. Örneğin, sunucunuz MYSERVER ve veritabanı örneğiniz INSTANCE, veritabanı adınız MyDatabase ve Windows Kimlik Doğrulamasını veritabanına erişmek için kullanmak istiyorsanız, bağlantı dizesi aşağıdaki kod örneğindeki gibi olmalıdır.
type dbSchema = SqlDataConnection<"Data Source=MYSERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;"> let db = dbSchema.GetDataContext() // Enable the logging of database activity to the console. db.DataContext.Log <- System.Console.Out
Şimdi bir türünüz var, dbSchema, veritabanı tablolarını temsil eden tüm üretilen türleri içeren temel bir türdür. Ayrıca bir nesneye sahip olabilirsiniz, db, üyeleri veritabanındaki tüm tablolar olan bir nesnedir. Tablo adları özelliklerdir ve bu tür özellikleri F# derleyicisi tarafından oluşturulur. Türler iç içe türü olarak dbSchema.ServiceTypes altında görünür. Bu nedenle, bu tablolardan satırlar için alınan herhangi bir veri o tablo için oluşturulan uygun türün bir örneğidir. Türün adı ServiceTypes.Table1.
F# dil sorgularının SQL sorgularını yorumlamasına alışkın olmak için, Log veri bağlama özelliğini ayarlayan satırı gözden geçirin.
Tür sağlayıcı tarafından oluşturulan türleri daha fazla keşfetmek için aşağıdaki kodu ekleyin.
let table1 = db.Table1
Kendi türünü görmek için table1 üzerinde gezdirin. Kendi türü System.Data.Linq.Table<dbSchema.ServiceTypes.Table1> ve genel bağımsız değişken türü, her satıra ait türün üretilen tür olduğunu belirtir, dbSchema.ServiceTypes.Table1. Derleyici, veritabanındaki her bir tablo için benzer bir tür oluşturur.
Veriyi sorgulama
Bu adımda, F# sorgu ifadelerini kullanarak bir sorgu yazın.
Verileri sorgulamak için
Şimdi veritabanındaki bu tablo için bir sorgu oluşturun. Aşağıdaki kodu ekleyin:
let query1 = query { for row in db.Table1 do select row } query1 |> Seq.iter (fun row -> printfn "%s %d" row.Name row.TestData1)
Kelimenin görünümü query bunun; benzer, tipik veritabanı sorgu sonuçları koleksiyonunu üreten hesaplama ifade türünde bir sorgu ifadesi olduğunu gösterir. Sorgu üzerinde gezdirirseniz, bunun bir Linq.QueryBuilder sınıfı (F#), sorgu hesaplama ifadesi tanımlayan bir tür örneği olduğunu görürsünüz. Üzerinde gezdirirseniz, query1, bunun bir IQueryable<T> örneği olduğunu görürsünüz . Adın da anlaşılacağı gibi IQueryable<T> sorgulanabilen fakat bir sorgu sonucu olmayan verileri temsil eder. Bir sorgu tembel bir değerlendirmeye bağlıdır, yani veritabanı yalnızca sorgu değerlendirildiğinde sorgulanabilir. Son satır, sorguyu Seq.iter üzerinden geçer. Sorgular sıralanabilir ve diziler gibi yinelenebilir. Daha fazla bilgi için bkz. Sorgu ifadelerini (F#).
Şimdi bir sorgu işlecini sorguya ekleyin. Daha karmaşık sorguları oluşturmak için kullanabileceğiniz birçok sayıda kullanılabilir sorgu işleçleri vardır. Bu örnek, sorgu değişkenini ortadan kaldırabileceğinizi ve yerine ardışık işleci kullanabileceğinizi gösterir.
query { for row in db.Table1 do where (row.TestData1 > 2) select row } |> Seq.iter (fun row -> printfn "%d %s" row.TestData1 row.Name)
Daha karmaşık bir sorguyu iki tablo katılımı ile birlikte ekleyin.
query { for row1 in db.Table1 do join row2 in db.Table2 on (row1.Id = row2.Id) select (row1, row2) } |> Seq.iteri (fun index (row1, row2) -> if (index = 0) then printfn "Table1.Id TestData1 TestData2 Name Table2.Id TestData1 TestData2 Name" printfn "%d %d %f %s %d %d %f %s" row1.Id row1.TestData1 row1.TestData2 row1.Name row2.Id (row2.TestData1.GetValueOrDefault()) (row2.TestData2.GetValueOrDefault()) row2.Name)
Gerçek kodda, sorgunuzdaki parametreler genellikle değerler veya değişkenlerdir, derleme zamanı sabitleri değildir. Sorguyu işlev içinde saran ve bir parametre alan, daha sonra bu işlevi 10 değeri ile çağıran aşağıdaki kodu ekleyin.
let findData param = query { for row in db.Table1 do where (row.TestData1 = param) select row } findData 10 |> Seq.iter (fun row -> printfn "Found row: %d %d %f %s" row.Id row.TestData1 row.TestData2 row.Name)
Null yapılabilir alanlar ile çalışma
Veritabanlarında, alanlar genellikle null değerlerine izin verir. .NET tür sisteminde, Null'a izin veren sıradan sayısal veri türlerini kullanamazsınız.Çünkü bu türler olası değer olarak Null'a sahip değildir. Bu nedenle, bu değerler Nullable<T> örnek türleri tarafından temsil edilir. Bu tür alanların değerlerine ad alanı ile doğrudan erişmek yerine, bazı ek adımlar eklemeniz gerekir. Null yapılabilir türün temel değerine erişmek için Value özelliğini kullanabilirsiniz. Eğer nesne değer yerine Null ise, Value özelliği bir istisna bulundurur. Değerin var olup olmadığını belirlemek için HasValue Boole yöntemini kullanabilirsiniz veya tüm durumlarda gerçek değere sahip olmasını sağlamak için GetValueOrDefault kullanabilirsiniz. Bir GetValueOrDefault kullanırsanız ve veritabanında null olduğundan; daha sonra dize türleri için boş bir dize gibi bir değerle, tam sayı türleri için 0 veya kayan nokta türleri için 0.0 ile yerini alır.
Bir sorgu içindeki where yan tümleci içinde bulunan null değerler üzerinde eşitlik testlerine veya karşılaştırmaya ihtiyaç duyduğunuzda, bir Linq.NullableOperators Modülü (F#) içindeki null yapılabilir işleçleri kullanın. Bunlar normal karşılaştırma işleçleri gibidir =, >, <=, ve benzeri, null değerlerinin olduğu bir işleçte soru işaretinin sol ya da sağ kısımda görünür olması dışında. Örneğin, işleç >? sağ tarafında bir null değerine sahip olan işleçten büyüktür. Bu işleçlerin işleyişi şöyledir ki eğer her iki tarafındaki ifade null ise, ifade false için değerlendirir. Bir where yan tümcesi içinde, genellikle null alanlar içeren satırlar seçili değildir ve sorgu sonuçlarında döndürülmez.
Null yapılabilir alanlar ile çalışma
Aşağıdaki kod, null değerleri ile çalışmayı gösterir; bir TestData1 null değerlere izin veren bir tamsayı alanı olduğunu düşünelim.
query { for row in db.Table2 do where (row.TestData1.HasValue && row.TestData1.Value > 2) select row } |> Seq.iter (fun row -> printfn "%d %s" row.TestData1.Value row.Name) query { for row in db.Table2 do // Use a nullable operator ?> where (row.TestData1 ?> 2) select row } |> Seq.iter (fun row -> printfn "%d %s" (row.TestData1.GetValueOrDefault()) row.Name)
Bir saklı yordamı çağırma
Veritabanı üzerindeki tüm saklı yordamlar F# tarafından çağrılabilir. Tür sağlayıcısı oluşturma içinde StoredProcedures için true statik parametre ayarlamalısınız. Sağlayıcı türü SqlDataConnection üretilen türleri yapılandırmak için kullanabileceğiniz birkaç statik yöntemler içerir. Tam bir tanımlama için bkz: SqlDataConnection türü sağlayıcı (F#). Veri bağlama türü üzerindeki bir yöntem her saklı yordam için oluşturulur.
Bir saklı yordamı çağırmak için
Saklı yordamlar null yapılabilir parametreleri alırsa, bu Nullable<T> değerine uygun geçmeniz gerekir. Bir skalar değeri veya tabloyu döndüren saklı yordam yönteminin dönüş değeri ISingleResult<T>, döndürülen veriye erişiminizi sağlayan özellikler içerir. Bağımsız değişken türü için ISingleResult<T> özel yordama bağlıdır ve aynı zamanda tür sağlayıcı tarafından üretilen türlerden biridir. Bir Procedure1 adlı saklı yordam için, Procedure1Result türdür. Tür Procedure1Result döndürülen bir tablo içindeki sütunların adlarını içerir veya skalar bir değer döndüren bir saklı yordam için onun dönüş değerini temsil eder.
Aşağıdaki kod Procedure1 veritabanı üzerinde, bir sütun döndüren bir sorgu parametresi olarak null yapılabilen iki tamsayıyı alan bir yordam olduğunu varsayar. Sütun TestData1 adındadır ve bir tamsayı döndürür.
type schema = SqlDataConnection<"Data Source=MYSERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;", StoredProcedures = true> let testdb = schema.GetDataContext() let nullable value = new System.Nullable<_>(value) let callProcedure1 a b = let results = testdb.Procedure1(nullable a, nullable b) for result in results do printfn "%d" (result.TestData1.GetValueOrDefault()) results.ReturnValue :?> int printfn "Return Value: %d" (callProcedure1 10 20)
Veritabanını güncelleme
LINQ DataContext türü, oluşturulan türlerle birlikte tam olarak yazılı biçimde işlenen veritabanı güncelleştirmelerini gerçekleştirmek için daha kolay yöntemler içerir.
Veritabanını güncellemek için
Aşağıdaki kodda, veritabanına birden fazla satır eklenir. Yalnızca bir satır eklemek isterseniz, yeni satırı eklemek amacıyla belirtmek için InsertOnSubmit kullanabilirsiniz. Birden çok satır ekliyorsanız, bunları koleksiyona koymalısınız ve InsertAllOnSubmit<TSubEntity> çağırmalısınız. Bu yöntemlerden herhangi birini aradığınızda, veritabanı hemen değişmez. Gerçekten değişiklikleri uygulamak için SubmitChanges çağırmalısınız. Varsayılan olarak, SubmitChanges çağırmadan önce yaptığınız her şey örtülü olarak aynı hareketin bir parçasıdır.
let newRecord = new dbSchema.ServiceTypes.Table1(Id = 100, TestData1 = 35, TestData2 = 2.0, Name = "Testing123") let newValues = [ for i in [1 .. 10] -> new dbSchema.ServiceTypes.Table3(Id = 700 + i, Name = "Testing" + i.ToString(), Data = i) ] // Insert the new data into the database. db.Table1.InsertOnSubmit(newRecord) db.Table3.InsertAllOnSubmit(newValues) try db.DataContext.SubmitChanges() printfn "Successfully inserted new rows." with | exn -> printfn "Exception:\n%s" exn.Message
Şimdi satırları silme işlemini çağırarak temizleyin.
// Now delete what was added. db.Table1.DeleteOnSubmit(newRecord) db.Table3.DeleteAllOnSubmit(newValues) try db.DataContext.SubmitChanges() printfn "Successfully deleted all pending rows." with | exn -> printfn "Exception:\n%s" exn.Message
Transact-SQL kodunu yürütme
Ayrıca Transact-SQL kodunu ExecuteCommand yöntemini DataContext sınıfı üzerinde kullanarak doğrudan belirtebilirsiniz.
Özel SQL komutlarını yürütmek için
Aşağıdaki kod, bir tabloya kayıt ekleme ve bir tablodan bir kaydı silmek için SQL komutlarının nasıl gönderileceğini gösterir.
try db.DataContext.ExecuteCommand("INSERT INTO Table3 (Id, Name, Data) VALUES (102, 'Testing', 55)") |> ignore with | exn -> printfn "Exception:\n%s" exn.Message try //AND Name = 'Testing' AND Data = 55 db.DataContext.ExecuteCommand("DELETE FROM Table3 WHERE Id = 102 ") |> ignore with | exn -> printfn "Exception:\n%s" exn.Message
Tam veri içeriğini kullanma
Önceki örneklerde, GetDataContext yöntemi Basitleştirilmiş veri içeriği veritabanı şeması için ne çağrıldığına ulaşılmak için kullanıldı. Çok sayıda kullanılabilir üye olmadığından dolayı basitleştirilmiş veri içeriğini sorgular oluşturulurken kullanmak daha kolaydır. Bu nedenle, IntelliSense özelliklerine göz attığınızda, tablolar ve saklı yordamlar gibi veritabanı yapısı üzerinde yoğunlaşabilirsiniz. Ancak, basitleştirilmiş veri içeriğiyle neler yapabileceğinize dair bir sınır vardır. Diğer eylemleri gerçekleştirebilmeyi sağlayan tam veri içeriği. aynı zamanda ServiceTypes içinde yer alır ve onu sağlamanız şartıyla DataContext statik paremetrelerinin adına sahiptir. Onu sağlamazsanız, veri içerik türünün adı sizin için diğer girdilerle SqlMetal.exe tarafından oluşturulur. Tam veri içeriği DataContext tarafından devralır ve ADO.NET veri türleri için başvurular da dahil olmak üzere, Connection nesnesi gibi, ExecuteCommand yöntemleri gibi temel sınıf üyelerini sergiler ve ExecuteQuery sorguları SQL içinde yazmak için ve hareketlerle açıkça çalışma olanağı için kullanabilirsiniz.
Tam veri içeriğini kullanmak için
Aşağıdaki kod, tam veri içeriği nesnesini alma ve doğrudan veritabanına karşı komutları yürütmek için kullanmayı gösterir. Bu durumda, iki komut aynı işlemin parçası olarak yürütülür.
let dbConnection = testdb.Connection let fullContext = new dbSchema.ServiceTypes.MyDatabase(dbConnection) dbConnection.Open() let transaction = dbConnection.BeginTransaction() fullContext.Transaction <- transaction try let result1 = fullContext.ExecuteCommand("INSERT INTO Table3 (Id, Name, Data) VALUES (102, 'A', 55)") printfn "ExecuteCommand Result: %d" result1 let result2 = fullContext.ExecuteCommand("INSERT INTO Table3 (Id, Name, Data) VALUES (103, 'B', -2)") printfn "ExecuteCommand Result: %d" result2 if (result1 <> 1 || result2 <> 1) then transaction.Rollback() printfn "Rolled back creation of two new rows." else transaction.Commit() printfn "Successfully committed two new rows." with | exn -> transaction.Rollback() printfn "Rolled back creation of two new rows due to exception:\n%s" exn.Message dbConnection.Close()
Verileri silme
Bu adım, bir veri tablosundan satırları silmeyi gösterir.
Satırları veritabanından silmek için
Şimdi, bir belirtilen tablodan satırları silen bir işlev yazarak eklenen satırları temizleyin, Table<TEntity> sınıfı örneği. Daha sonra silmek istediğiniz tüm satırları bulmak için bir sorgu yazın ve sorgu sonuçlarını deleteRows işlevi içine yöneltin. Bu kod, fonksiyon bağımsız değişkenlerinin kısmi uygulamasını sağlama yeteneğinden yararlanır.
let deleteRowsFrom (table:Table<_>) rows = table.DeleteAllOnSubmit(rows) query { for rows in db.Table3 do where (rows.Id > 10) select rows } |> deleteRowsFrom db.Table3 db.DataContext.SubmitChanges() printfn "Successfully deleted rows with Id greater than 10 in Table3."
Sınama veritabanı oluşturma
Bu bölümde, bu izlenecek yolda kullanmak için sınama veritabanının nasıl ayarlandığı gösterilir.
Veritabanı bazı şekilde değiştirirseniz, tür sağlayıcısını sıfırlamanız gerektiğine dikkat edin. Tür sağlayıcısını sıfırlamak için tür sağlayıcısı içeren projeyi temizleyin veya yeniden derleyin.
Test veritabanı oluşturmak için
Bir Sunucu Gezgini içinde, Veri Bağlantıları düğümü için kısayol menüsünü açın, ve ardından Bağlantı Ekle seçin. Add Connection iletişim kutusu görüntülenir.
Bir Sunucu Adı kutusu içinde, yönetimsel erişiminiz olan bir SQL Server örneğinin adını belirtin, ya da eğer bir sunucuya erişiminiz yoksa (localdb\v11.0) belirtin. SQL Express LocalDB makineniz üzerinde geliştirme ve sınama için bir hafif veritabanı sunucusu sağlar. Server Explorer içinde Data Connections altında yeni bir düğüm oluşturulur. LocalDB hakkında daha fazla bilgi için, bkz: İzlenecek yol: Yerel Veritabanı Oluşturma.
Yeni bağlantı düğümü için kısayol menüsünü açın, ve ardından New Query seçin.
Aşağıdaki SQL komut dosyasını kopyalayın, sorgu düzenleyicisine yapıştırın ve sonra Execute araç çubuğundaki düğmesini tıklayın veya Ctrl + SHIFT +E tuşlarını seçin.
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO USE [master]; GO IF EXISTS (SELECT * FROM sys.databases WHERE name = 'MyDatabase') DROP DATABASE MyDatabase; GO -- Create the MyDatabase database. CREATE DATABASE MyDatabase; GO -- Specify a simple recovery model -- to keep the log growth to a minimum. ALTER DATABASE MyDatabase SET RECOVERY SIMPLE; GO USE MyDatabase; GO -- Create the Table1 table. CREATE TABLE [dbo].[Table1] ( [Id] INT NOT NULL, [TestData1] INT NOT NULL, [TestData2] FLOAT (53) NOT NULL, [Name] NTEXT NOT NULL, PRIMARY KEY CLUSTERED ([Id] ASC) ); --Create Table2. CREATE TABLE [dbo].[Table2] ( [Id] INT NOT NULL, [TestData1] INT NULL, [TestData2] FLOAT (53) NULL, [Name] NTEXT NOT NULL, PRIMARY KEY CLUSTERED ([Id] ASC) ); -- Create Table3. CREATE TABLE [dbo].[Table3] ( [Id] INT NOT NULL, [Name] NVARCHAR (50) NOT NULL, [Data] INT NOT NULL, PRIMARY KEY CLUSTERED ([Id] ASC) ); GO CREATE PROCEDURE [dbo].[Procedure1] @param1 int = 0, @param2 int AS SELECT TestData1 FROM Table1 RETURN 0 GO -- Insert data into the Table1 table. USE MyDatabase INSERT INTO Table1 (Id, TestData1, TestData2, Name) VALUES(1, 10, 5.5, 'Testing1'); INSERT INTO Table1 (Id, TestData1, TestData2, Name) VALUES(2, 20, -1.2, 'Testing2'); --Insert data into the Table2 table. INSERT INTO Table2 (Id, TestData1, TestData2, Name) VALUES(1, 10, 5.5, 'Testing1'); INSERT INTO Table2 (Id, TestData1, TestData2, Name) VALUES(2, 20, -1.2, 'Testing2'); INSERT INTO Table2 (Id, TestData1, TestData2, Name) VALUES(3, NULL, NULL, 'Testing3'); INSERT INTO Table3 (Id, Name, Data) VALUES (1, 'Testing1', 10); INSERT INTO Table3 (Id, Name, Data) VALUES (2, 'Testing2', 100);
Ayrıca bkz.
Görevler
İzlenecek yol: F# türleriyle dbml dosyasından (F#) oluşturma
Başvuru
SqlDataConnection türü sağlayıcı (F#)
SqlMetal.exe (kod oluşturma aracı)