Share via


Exemplarische Vorgehensweise: Zugreifen auf eine SQL-Datenbank mithilfe von Typanbietern (F#)

In dieser exemplarischen Vorgehensweise wird erläutert, wie der in F# 3.0 verfügbare SqlDataConnection-Typanbieter (LINQ to SQL) verwendet wird, um bei einer aktiven Datenbankverbindung Typen für Daten in einer SQL-Datenbank zu generieren.Wenn keine aktive Verbindung mit der Datenbank besteht, Sie aber über eine LINQ to SQL-Schemadatei (DBML-Datei) verfügen, lesen Sie das Thema Exemplarische Vorgehensweise: Generieren von F#-Typen aus einer DBML-Datei (F#).

In dieser exemplarischen Vorgehensweise werden die folgenden Aufgaben beschrieben.Diese Aufgaben müssen in der hier genannten Reihenfolge ausgeführt werden, um die exemplarische Vorgehensweise erfolgreich abschließen zu können:

  • Preparing a test database

  • Creating the project

  • Setting up a type provider

  • Querying the data

  • Working with nullable fields

  • Calling a stored procedure

  • Updating the database

  • Executing Transact-SQL code

  • Using the full data context

  • Deleting data

  • Create a test database (as needed)

Vorbereiten einer Testdatenbank

Erstellen Sie auf einem Server, auf dem SQL Server ausgeführt wird, eine Datenbank für Testzwecke.Hierfür können Sie das Datenbankerstellungsskript am Ende dieser Seite im Abschnitt MyDatabase Create Script verwenden.

So bereiten Sie eine Testdatenbank vor

  • Um MyDatabase Create Script auszuführen, öffnen Sie das Menü Ansicht und wählen anschließend SQL Server-Objekt-Explorer, oder drücken Sie die Tasten Ctrl+\, Ctrl+S.Öffnen Sie im Fenster SQL Server-Objekt-Explorer das Kontextmenü für die entsprechende Instanz, wählen Sie Neue Abfrage aus, kopieren Sie das Skript am Ende dieser Seite, und fügen Sie es anschließend in den Editor ein.Um das SQL-Skript ausführen, klicken Sie auf der Symbolleiste auf das Dreieckssymbol, oder drücken Sie Ctrl+Q.Weitere Informationen zum SQL Server-Objekt-Explorer finden Sie unter Entwicklung verbundener Datenbanken.

Erstellen des Projekts

Als Nächstes erstellen Sie ein F#-Anwendungsprojekt.

So erstellen Sie das Projekt und richten es ein

  1. Erstellen Sie ein neues F#-Anwendungsprojekt.

  2. Fügen Sie Verweise auf .FSharp.Data.TypeProviders sowie auf System.Data und System.Data.Linq hinzu.

  3. Öffnen Sie die entsprechenden Namespaces, indem Sie die folgenden Codezeilen am Anfang der F#-Codedatei Program.fs einfügen.

    open System
    open System.Data
    open System.Data.Linq
    open Microsoft.FSharp.Data.TypeProviders
    open Microsoft.FSharp.Linq
    
  4. Wie bei den meisten F#-Programmen, können Sie den Code in dieser exemplarischen Vorgehensweise als kompiliertes Programm oder interaktiv als Skript ausführen.Wenn Sie die Verwendung von Skripts vorziehen, öffnen Sie das Kontextmenü für den Projektknoten, wählen Sie Neues Element hinzufügen, fügen Sie eine F#-Skriptdatei hinzu, und fügen Sie dann den Code aus den vorherigen Schritten in das Skript ein.Zum Laden der Assemblyverweise müssen Sie außerdem die folgenden Zeilen am Anfang der Datei hinzufügen.

    #r "System.Data.dll"
    #r "FSharp.Data.TypeProviders.dll"
    #r "System.Data.Linq.dll"
    

    Im Anschluss können Sie jeden hinzugefügten Codeblock auswählen und durch Drücken von Alt+Enter in F# Interactive ausführen.

Installieren eines Typanbieters

In diesem Schritt erstellen Sie einen Typanbieter für Ihr Datenbankschema.

So richten Sie den Typanbieter für eine direkte Datenbankverbindung ein

  • Es gibt zwei wichtige Codezeilen, die erforderlich sind, um die Typen zu erstellen, die Sie zum Abfragen einer SQL-Datenbank mit dem Typanbieter verwenden können.Zuerst instanziieren Sie den Typanbieter.Hierzu erstellen Sie eine einer Typabkürzung ähnliche SqlDataConnection mit einem statischen generischen Parameter.SqlDataConnection ist ein SQL-Typanbieter und darf nicht mit dem SqlConnection-Typ verwechselt werden, der bei der ADO.NET-Programmierung verwendet wird.Wenn Sie Zugriff auf die Datenbank haben, mit der Sie eine Verbindung herstellen möchten, und die richtige Verbindungszeichenfolge kennen, rufen Sie den Typanbieter mit folgendem Code auf.Ersetzen Sie die Zeichenfolge im Beispiel durch die eigene Verbindungszeichenfolge.Wenn der Server MYSERVER heißt, der Name der Datenbankinstanz INSTANCE und der Datenbankname MyDatabase lautet und Sie mithilfe der Windows-Authentifizierung auf die Datenbank zugreifen möchten, ergibt sich die im folgenden Beispielcode gezeigte Verbindungszeichenfolge.

    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
    

    Sie verfügen nun über den Typ dbSchema. Dieser übergeordnete Typ umfasst alle für die einzelnen Datenbanktabellen generierten Typen.Sie können außerdem auf das Objekt db zugreifen, das alle Tabellen in der Datenbank als Member enthält.Die Tabellennamen sind Eigenschaften. Die Typen dieser Eigenschaften werden vom F#-Compiler generiert.Die Typen selbst werden als geschachtelte Typen unter dbSchema.ServiceTypes abgelegt.Daher stellen alle Daten, die für Zeilen dieser Tabellen abgerufen werden, eine Instanz des jeweiligen Typs dar, der für diese Tabelle generiert wurde.Der Name des Typs ist ServiceTypes.Table1.

    Um zu lernen, wie die Programmiersprache F# Abfragen beim Interpretieren in SQL-Abfragen übersetzt, betrachten Sie die Zeile, in der die Log-Eigenschaft des Datenkontexts festgelegt wird.

    Um die vom Typanbieter erstellten Typen weiter verarbeiten zu können, fügen Sie den folgenden Code hinzu.

    let table1 = db.Table1
    

    Zeigen Sie mit dem Mauszeiger auf table1, um Informationen zum Typ anzuzeigen.Der Typ ist System.Data.Linq.Table<dbSchema.ServiceTypes.Table1>, und das generische Argument impliziert, dass der Typ jeder Zeile der generierte Typ dbSchema.ServiceTypes.Table1 ist.Der Compiler erstellt einen ähnlichen Typ für jede Tabelle in der Datenbank.

Abfragen der Daten

In diesem Schritt schreiben Sie eine Abfrage mit F#-Abfrageausdrücken.

So fragen Sie Daten ab

  1. Erstellen Sie jetzt eine Abfrage für diese Tabelle in der Datenbank.Fügen Sie den folgenden Code hinzu.

    let query1 =
            query {
                for row in db.Table1 do
                select row
            }
    query1 |> Seq.iter (fun row -> printfn "%s %d" row.Name row.TestData1)
    

    Durch die Angabe des Worts query wird angezeigt, dass der nachfolgende Text ein Abfrageausdruck ist, also eine Form eines Berechnungsausdrucks, der eine Ergebnisauflistung generiert, die einer typischen Datenbankabfrage ähnelt.Wenn Sie mit dem Mauszeiger auf eine Abfrage zeigen, sehen Sie, dass es sich um eine Instanz von Linq.QueryBuilder-Klasse (F#) handelt, ein Typ, der den Abfragenberechnungsausdruck definiert.Wenn Sie mit dem Mauszeiger auf query1 zeigen, wird angezeigt, dass dies eine Instanz von IQueryable<T> ist.Wie der Name bereits sagt, gibt IQueryable<T> die Daten wieder, die abgefragt werden können, und nicht das Ergebnis einer Abfrage.Abfragen werden verzögert ausgewertet, das heißt, dass die Datenbank nur abgefragt wird, während die Abfrageauswertung stattfindet.In der letzten Zeile wird die Abfrage an Seq.iter übergeben.Abfragen sind aufzählbar und können wie Sequenzen durchlaufen werden.Weitere Informationen finden Sie unter Abfrageausdrücke (F#).

  2. Fügen Sie der Abfrage nun einen Abfrageoperator hinzu.Es sind mehrere Abfrageoperatoren verfügbar, die Sie verwenden können, um komplexe Abfragen zu erstellen.In diesem Beispiel wird außerdem gezeigt, dass Sie die Abfragevariable ausschließen und stattdessen einen Pipelineoperator verwenden können.

    query {
            for row in db.Table1 do
            where (row.TestData1 > 2)
            select row
          }
    |> Seq.iter (fun row -> printfn "%d %s" row.TestData1 row.Name)
    
  3. Fügen Sie eine komplexere Abfrage mit einem Join für zwei Tabellen hinzu.

    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)
    
  4. In echtem Code für den Produktiveinsatz sind die Parameter der Abfrage meist Werte oder Variablen und keine Kompilierzeitkonstanten.Fügen Sie den folgenden Code hinzu, der die Abfrage in eine Funktion mit einem Parameter einschließt und anschließend diese Funktion mit dem Wert 10 aufruft.

    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)
    

Arbeiten mit Feldern, die NULL-Werte zulassen

Felder in Datenbanken lassen häufig NULL-Werte zu.Im .NET-Typsystem können Sie die normalen numerischen Datentypen nicht für Daten verwenden, die NULL-Werte zulassen, da diese Typen NULL nicht als zulässigen Wert akzeptieren.Daher werden diese Werte durch Instanzen des Nullable<T>-Typs dargestellt.Statt auf den Wert dieser Felder direkt über den Namen zuzugreifen, müssen Sie einige zusätzliche Schritte einfügen.Sie können die Value-Eigenschaft verwenden, um auf den zugrunde liegenden Wert eines Typs zuzugreifen, der NULL-Werte zulässt.Die Value-Eigenschaft löst eine Ausnahme aus, wenn das Objekt statt eines Werts NULL ist.Sie können mit der boolesche Methode HasValue bestimmen, ob ein Wert vorhanden ist, oder Sie verwenden GetValueOrDefault, um sicherzustellen, dass Sie in allen Fällen einen tatsächlichen Wert erhalten.Wenn Sie GetValueOrDefault verwenden und in der Datenbank ein NULL-Wert gespeichert ist, wird dieser durch einen geeigneten Wert ersetzt, wie z. B. durch eine leere Zeichenfolge bei Zeichenfolgentypen, durch 0 bei ganzzahligen Typen oder durch 0,0 bei Gleitkommatypen.

Wenn Sie Gleichheitstests oder Vergleiche mit Werten, die NULL-Werte zulassen, in einer where-Klausel einer Abfrage ausführen müssen, können Sie die Operatoren in Linq.NullableOperators-Modul (F#) verwenden, die NULL-Werte zulassen.Diese entsprechen den regulären Vergleichsoperatoren =, >, <= usw., es wird jedoch zusätzlich ein Fragezeichen links oder rechts von dem Operator hinzugefügt, der Werte verarbeiten muss, die NULL-Werte zulassen.Beispielsweise ist der Operator >? ein Größer-als-Operator mit einem Wert, der NULL-Werte zulässt, auf der rechten Seite.Wenn eine Seite des Ausdrucks NULL ist, ergibt der Ausdruck false.In einer where-Klausel bedeutet dies üblicherweise, dass Zeilen, die Felder mit NULL-Werten enthalten, nicht ausgewählt und in den Abfrageergebnissen nicht zurückgegeben werden.

So arbeiten Sie mit Feldern, die NULL-Werte zulassen

  • Der folgende Code veranschaulicht die Verarbeitung von Werten, die NULL-Werte zulassen. Es wird davon ausgegangen, dass TestData1 ein Ganzzahlfeld ist, das NULL-Werte zulässt.

    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)
    

Aufrufen einer gespeicherten Prozedur

Alle gespeicherten Prozeduren der Datenbank können in F# aufgerufen werden.Sie müssen den statischen Parameter StoredProcedures in der Typanbieterinstanziierung auf true festlegen.Der Typanbieter SqlDataConnection enthält mehrere statische Methoden, die Sie verwenden können, um die Typen zu konfigurieren, die generiert werden.Eine ausführliche Beschreibung hierzu finden Sie unter SqlDataConnection-Typanbieter (F#).Für jede gespeicherte Prozedur wird eine Methode im Datenkontexttyp generiert.

So rufen Sie eine gespeicherte Prozedur auf

  • Wenn die gespeicherten Prozeduren Parameter akzeptieren, die auf NULL festgelegt werden können, müssen Sie einen entsprechenden Nullable<T>-Wert übergeben.Der Rückgabewert der Methode einer gespeicherten Prozedur, die einen Skalarwert oder eine Tabelle zurückgibt, ist ISingleResult<T>. Dieser enthält Eigenschaften, über die Sie auf die zurückgegebenen Daten zugreifen können.Das Typargument für ISingleResult<T> ist abhängig von der jeweiligen Prozedur und ist ebenfalls einer der vom Typanbieter generierten Typen.Für eine gespeicherte Prozedur mit dem Namen Procedure1 lautet der Typ Procedure1Result.Der Typ Procedure1Result enthält die Namen der Spalten in einer Rückgabetabelle, oder, bei einer gespeicherten Prozedur, die einen Skalarwert zurückgibt, den Rückgabewert.

    Im folgenden Code wird davon ausgegangen, dass eine Prozedur Procedure1 in der Datenbank vorhanden ist, die zwei ganze Zahlen, die NULL-Werte zulassen, als Parameter akzeptiert und die eine Abfrage ausführt, die eine Spalte mit dem Namen TestData1 zurückgibt. Anschließend gibt die Prozedur eine ganze Zahl zurück.

    
    
    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)
    

Aktualisieren der Datenbank

Der LINQ-DataContext-Typ enthält Methoden, die es erleichtern, mit den generierten Typen transaktive und vollständig typisierte Datenbankupdates auszuführen.

So aktualisieren Sie die Datenbank

  1. Im folgenden Code werden der Datenbank einige Zeilen hinzugefügt.Wenn Sie nur eine Zeile hinzufügen, können Sie InsertOnSubmit verwenden, um die neue hinzuzufügende Zeile anzugeben.Wenn Sie mehrere Zeilen einfügen, sollten Sie sie in einer Auflistung zusammenfassen und InsertAllOnSubmit<TSubEntity> aufrufen.Beim Aufrufen einer dieser Methoden wird die Datenbank noch nicht sofort geändert.Sie müssen SubmitChanges aufrufen, um die Änderungen tatsächlich zu übernehmen.Standardmäßig werden alle Vorgänge, die Sie vor dem Aufruf von SubmitChanges ausführen, implizit als eine Transaktion ausgeführt.

    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
    
  2. Bereinigen Sie jetzt die Zeilen wieder, indem Sie einen Löschvorgang aufrufen.

    // 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
    

Ausführen von Transact-SQL-Code

Sie können auch direkt Transact-SQL angeben, indem Sie die ExecuteCommand-Methode der DataContext-Klasse verwenden.

So führen Sie eigene SQL-Befehle aus

  • Der folgende Code zeigt, wie Sie SQL-Befehle übermitteln können, um einen Datensatz in eine Tabelle einzufügen oder einen Datensatz aus einer Tabelle zu löschen.

    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
    

Verwenden des vollständigen Datenkontexts

In den vorherigen Beispielen wurde die GetDataContext-Methode verwendet, um den so genannten vereinfachten Datenkontext für das Datenbankschema abzurufen.Der vereinfachte Datenkontext ist leichter zu handhaben, wenn Sie Abfragen erstellen, da nicht so viele Member vorhanden sind.Wenn Sie die Eigenschaften in IntelliSense durchsuchen, können Sie sich so auf die Datenbankstruktur, wie die Tabellen und gespeicherten Prozeduren, konzentrieren.Der vereinfachte Datenkontext ist jedoch in seinem Funktionsumfang eingeschränkt.Daher ist zusätzlich ein vollständiger Datenkontext vorhanden, der die Möglichkeit bietet, weitere Aktionen auszuführen.Dieser befindet sich unter ServiceTypes und trägt den Namen des statischen DataContext-Parameters, sofern dieser angegeben wurde.Wenn er nicht angegeben wurde, wird der Name des Datenkontexttyps von SqlMetal.exe automatisch basierend auf den anderen vorhandenen Eingaben generiert.Der vollständige Datenkontext erbt von DataContext und macht die Member der Basisklasse verfügbar, einschließlich der Verweise auf ADO.NET-Datentypen, wie das Connection-Objekt, oder Methoden wie ExecuteCommand und ExecuteQuery, die Sie verwenden können, um Abfragen in SQL zu schreiben oder explizit mit Transaktionen zu arbeiten.

So verwenden Sie den vollständigen Datenkontext

  • Im folgenden Code wird das Abrufen eines vollständigen Datenkontextobjekts veranschaulicht und gezeigt, wie Befehle direkt gegen die Datenbank ausgeführt werden können.In diesem Fall werden zwei Befehle als Teil derselben Transaktion ausgeführt.

    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()
    

Löschen von Daten

In diesem Schritt wird gezeigt, wie Zeilen aus einer Datentabelle gelöscht werden.

So löschen Sie Zeilen aus der Datenbank

  • Löschen Sie jetzt alle hinzugefügten Zeilen, indem Sie eine Funktion schreiben, die Zeilen aus einer angegebenen Tabelle (einer Instanz der Table<TEntity>-Klasse) löscht.Schreiben Sie dann eine Abfrage, um alle Zeilen zu suchen, die gelöscht werden sollen, und leiten Sie die Ergebnisse der Abfrage weiter an die deleteRows-Funktion.Dieser Code nutzt die Möglichkeit, Funktionsargumente nur teilweise angeben zu können.

    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."
    

Erstellen einer Testdatenbank

In diesem Abschnitt wird erläutert, wie die Testdatenbank für diese exemplarische Vorgehensweise installiert wird.

Beachten Sie, dass Sie den Typanbieter bei allen Veränderungen der Datenbank zurücksetzen müssen.Um den Typanbieter zurückzusetzen, bereinigen oder erstellen Sie das Projekt neu, das den Typanbieter enthält.

So erstellen Sie die Testdatenbank

  1. Öffnen Sie im Server-Explorer das Kontextmenü für den Knoten Datenverbindungen, und wählen Sie dann Verbindung hinzufügen.Das Dialogfeld Verbindung hinzufügen wird angezeigt.

  2. Im Feld Servername geben Sie den Namen einer Instanz von SQL Server an, in der Sie administrativen Zugriff haben. Wenn Sie keinen Zugriff auf einen Server haben, geben Sie an (localdb\v11.0) ein.SQL Express LocalDB stellt einen einfachen Datenbankserver für Entwicklung und Tests auf dem Computer bereit.Ein neuer Knoten wird in Server-Explorer unter Datenverbindungen erstellt.Weitere Informationen über LocalDB finden Sie unter Exemplarische Vorgehensweise: Erstellen einer LocalDB-Datenbank.

  3. Öffnen Sie das Kontextmenü für den neuen Verbindungsknoten, und wählen Sie Neue Abfrage.

  4. Kopieren Sie das folgende SQL-Skript, fügen Sie es in den Abfrage-Editor ein, und wählen Sie die Schaltfläche Ausführen auf der Symbolleiste (oder die Tasten STRG+UMSCHALT+E).

    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);
    

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Generieren von F#-Typen aus einer DBML-Datei (F#)

Referenz

SqlDataConnection-Typanbieter (F#)

Abfrageausdrücke (F#)

SqlMetal.exe (Tool zur Codegenerierung)

Weitere Ressourcen

Typanbieter

LINQ to SQL