How to: Create, Read, Update, and Delete Data using LINQ

[This content is no longer valid. For the latest information on "M", "Quadrant", SQL Server Modeling Services, and the Repository, see the Model Citizen blog.]

This topic provides examples of how to programmatically create, read, update, and delete data in the SQL Server Modeling Services database by using Language-Integrated Query (LINQ). For more information about LINQ, see Introduction to LINQ.

Note

This topic uses a HumanResources model. For more information about how to create this model and install it in the Modeling Services database, see How to: Install the HumanResources Sample Model using Visual Studio.

In this tutorial, you will perform the following tasks.

  • Use the Object Relational Designer (O/R) to add LINQ classes and methods for target objects in the Modeling Services database.

  • Create a new Folder named HumanResourcesExampleFolder that contains employee instances.

  • Add employee instances to the [HumanResources].[Employees] table.

  • Query a list of employees from the database.

  • Update an employee instance.

  • Remove the HumanResourcesExampleFolder Folder and its contents.

To create a connection to the Modeling Services database

  1. Open Visual Studio 2010.

  2. On the View menu, point to Other Windows, and then click Server Explorer.

  3. In the Server Explorer window, right-click the Data Connections folder, and then select Add Connection.

  4. In the Add Connection dialog, enter the server name and select the database name of the Modeling Services database.

    Tip

    Note that if the Modeling Services database is on the same machine, you can enter (local) for the server name. The default name for the database is "Repository".

  5. Click the OK button to create the connection.

To create a LINQ console application

  1. Create a new console application project. In the New Project dialog, select Visual Basic or Visual C#. Select the Console Application template, and name it RepAccess_LINQ. Use the default Location.

  2. On the Project menu, click Add New Item.

  3. In the Installed Templates pane, select Data.

  4. In the list of data templates, select LINQ to SQL Classes.

  5. In the Name edit box, type Repository.dbml

  6. Click the Add button. The two-paned Object Relational (O/R) Designer should open.

  7. In the Server Explorer window, expand the Modeling Services database connection, and then expand Tables.

  8. Drag the "Employees (Human Resources)" table to the left pane of the O/R Designer.

  9. Collapse the list of tables in Server Explorer.

  10. Expand Views.

  11. Drag and "Folders (Repository.Item)" view to the left pane of the O/R Designer.

  12. Collapse the list of views in Server Explorer.

  13. Expand Functions.

  14. Drag the "PathsFolder (Repository.Item)" function to the right pane of the O/R Designer.

To modify the generated Employee and Folder data classes

  1. In the O/R Designer for Repository.dbxml, select the Id column of the Folders data class.

  2. In the Properties window, change the Primary Key property to True for the Id column.

  3. Note

    The steps in this section are necessary, because the Repository.Item schema uses updatable views. A view does not have a primary key, but the view targets a table with a primary key. The O/R Designer cannot make this assumption, so the change must be made manually.

  4. In the O/R Designer, select the last field of the Folder data class. It might be named Folder1 or just Folder.

  5. Change the Name property for this column to ParentFolder.

  6. On the Build menu, click Build Solution.

To override the insert behavior in LINQ

  1. In the O/R Designer for Repository.dbxml, right-click a blank area of the designer, and then select View Code.

  2. Include two namespaces to the top of this source file: System.Linq and System.Collections.Generic.

    Imports System.Linq
    Imports System.Collections.Generic
    
    using System.Linq;
    using System.Collections.Generic;
    
  3. Add definitions for two partial methods to the RepositoryDataContext class to override the insertion routines for the generated Folder data class.

    Note

    This is a necessary step, because the normal insertion routines call the SQL Server function, SCOPE_IDENTITY, to get the identifier for the inserted row. However, because the view inserts rows into the underlying tables using triggers, SCOPE_IDENTITY returns a null value. To prevent errors, the insertion is performed manually and then the identifiers are retrieved afterward.

    Private Sub InsertFolder(ByVal instance As Folder)
       ExecuteCommand("insert into [Repository.Item].[Folders] (Name, Folder) " & _
          "values ({0}, {1})", instance.Name, instance.ParentFolder)
    End Sub
    
    partial void InsertFolder(Folder instance)
    {
       ExecuteCommand("insert into [Repository.Item].[Folders] (Name, Folder) " +
          "values ({0}, {1})", instance.Name, instance.ParentFolder);
    }
    

To use the generated LINQ classes

  1. Open the main source file (Program.cs in Visual C# or Module1.vb in Visual Basic).

  2. Include three namespaces to the top of the source file: System, System.Linq, and System.Data.Linq. In a Visual C# project, replace any existing using statements with the ones below.

    Imports System
    Imports System.Linq
    Imports System.Data.Linq
    
    using System;
    using System.Linq;
    using System.Data.Linq;
    
  3. Add exception handling in the Main method using the following code.

    Sub Main()
       Try
    
       Catch exception As Exception
          Console.WriteLine("An unexpected error occurred: {0}" & Environment.NewLine, exception.Message)
       Finally
          Console.ReadKey()
       End Try
    End Sub
    
    static void Main(string[] args)
    {
       try
       {
    
       }
       catch (Exception exception)
       {
          Console.WriteLine("An unexpected error occurred: {0}" + Environment.NewLine, exception.Message);
       }
       finally
       {
          Console.ReadKey();
       }
    }
    
  4. Inside the try-block, add code to create a local variable, db, for the LINQ-generated RepositoryDataContext class.

    ' Create the DataContext object for the Repository. 
    Dim db As RepositoryDataContext = New RepositoryDataContext()
    
    // Create the DataContext object for the Repository. 
    RepositoryDataContext db = new RepositoryDataContext();
    
  5. Add local variables to use in later steps.

    Note

    Note that the Long? and long? type names specifies a long type that is nullable.

    ' Reference strongly typed tables for the [Repository.Item].[Folders]
    ' view and the [HumanResources].[Employees] table.
    Dim foldersView As Table(Of Folder) = db.Folders
    Dim employeesTable As Table(Of Employee) = db.Employees
    
    Dim humanResourcesFolderId As Long?
    
    // Reference strongly typed tables for the [Repository.Item].[Folders]
    // view and the [HumanResources].[Employees] table.
    Table<Folder> foldersView = db.Folders;
    Table<Employee> employeesTable = db.Employees;
    
    long? humanResourcesFolderId;
    

To create a new Modeling Services Folder

  1. Immediately following the code in the previous section, add code that calls the LINQ wrapper for the [Repository.Item].[PathsFolder] function to discover if the target HumanResourcesExampleFolder Folder already exists.

    ' Look to see if the target Modeling Services Folder already 
    ' exists by using the [Repository.Item].[PathsFolder] function.
    Console.WriteLine("Looking for the Repository/HumanResourcesFolder...")
    humanResourcesFolderId = db.PathsFolder("Repository/HumanResourcesFolder")
    
    // Look to see if the target Modeling Services Folder already 
    // exists by using the [Repository.Item].[PathsFolder] function.
    Console.WriteLine("Looking for the Repository/HumanResourcesFolder...");
    humanResourcesFolderId = db.PathsFolder("Repository/HumanResourcesFolder");
    
  2. If the target Folder does not exist, insert a new Folder into the [Repository.Item].[Folders] view. Call the [Repository.Item].[PathsFolder] function again to retrieve the identity of the new Folder.

    ' If the target Folder does not exist, create it.
    If (humanResourcesFolderId.HasValue = False) Then
       ' First obtain the Folder for the system-defined "Repository" Folder.
       Dim folderRepository As Integer?
       folderRepository = _
          (From folder In foldersView _
          Where folder.Name = "Repository" _
          Select folder.Id).SingleOrDefault()
    
       If (folderRepository.HasValue) Then
          ' Create the new Folder and submit the changes.
          ' Refer to the identifier for the "Repository" Folder to make
          ' this new Folder a subFolder under Repository.
          Dim folderNew As Folder = New Folder()
          folderNew.Name = "HumanResourcesFolder"
          folderNew.ParentFolder = folderRepository
    
          foldersView.InsertOnSubmit(folderNew)
    
          db.SubmitChanges()
    
          ' Obtain the value of the inserted Folder
          humanResourcesFolderId = db.PathsFolder("Repository/HumanResourcesFolder")
       Else
          humanResourcesFolderId = 1
       End If
    End If
    Console.WriteLine("HumanResourcesExampleFolder: Id = {0}" + Environment.NewLine, humanResourcesFolderId.ToString())
    
    // If the target Folder does not exist, create it.
    if (humanResourcesFolderId.HasValue == false)
    {
       // First obtain the Folder for the system-defined "Repository" Folder.
       int? folderRepository =
          (from folder in foldersView
           where folder.Name == "Repository"
           select folder.Id).SingleOrDefault();
    
       if (folderRepository.HasValue)
       {
          // Create the new Folder and submit the changes.
          // Refer to the identifier for the "Repository" Folder to make
          // this new Folder a subFolder under Repository.
          Folder folderNew = new Folder();
          folderNew.Name = "HumanResourcesFolder";
          folderNew.ParentFolder = (int)folderRepository;
    
          foldersView.InsertOnSubmit(folderNew);
    
          db.SubmitChanges();
    
          // Obtain the value of the inserted Folder
          humanResourcesFolderId = db.PathsFolder("Repository/HumanResourcesFolder");
       }
       else
          humanResourcesFolderId = 1;
    }
    Console.WriteLine("HumanResourcesExampleFolder: Id = {0}" + Environment.NewLine, humanResourcesFolderId.ToString());
    

To create a new employee in the [HumanResources].[Employees] table

  1. Immediately following the code in the previous section, add the following code that creates a new employee row in the [HumanResources].[Employees] table.

    Note

    Note that this new employee instance is associated with the identifier of the previously created HumanResourcesFolder Folder.

    ' Create the new employee and submit the changes. Use the HumanResourcesFolder
    ' identifier for the Folder column of the Employee item.
    Console.WriteLine("Creating new employee: Name={0}", "John")
    Dim employeeNew As Employee = New Employee()
    employeeNew.Name = "John"
    employeeNew.Folder = humanResourcesFolderId
    
    employeesTable.InsertOnSubmit(employeeNew)
    
    db.SubmitChanges()
    
    Console.WriteLine("New employee: Id = {0}", employeeNew.Id)
    
    // Create the new employee and submit the changes. Use the HumanResourcesFolder
    // identifier for the Folder column of the Employee item.
    Console.WriteLine("Creating new employee: Name={0}", "John");
    Employee employeeNew = new Employee();
    employeeNew.Name = "John";
    employeeNew.Folder = (int)humanResourcesFolderId;
    
    employeesTable.InsertOnSubmit(employeeNew);
    
    db.SubmitChanges();
    
    Console.WriteLine("New employee: Id = {0}", employeeNew.Id);
    

To query the contents of the [HumanResources].[Employees] table

  1. Add the following code that uses a LINQ query to list the contents of the [HumanResources].[Employees] table. You should see the new employee, "John", created in the previous step.

    ' Display the current list of Employees.
    Console.WriteLine("Employees:")
    Dim employeeQuery = _
       From employee In employeesTable _
       Select employee
    
    For Each employee In employeeQuery
       Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder)
    Next
    
    // Display the current list of Employees.
    Console.WriteLine("Employees:");
    var employeeQuery =
        from employee in employeesTable
        select employee;
    
    foreach (var employee in employeeQuery)
       Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder);
    

To update the [HumanResources].[Employees] table

  1. Add the following code to change the name of the employee from "John" to "Jonathan".

    ' Update the [HumanResources].[Employees] table.
    Console.WriteLine(Environment.NewLine + "Updating the employees name to Jonathan...")
    employeeNew.Name = "Jonathan"
    db.SubmitChanges()
    
    // Update the [HumanResources].[Employees] table.
    Console.WriteLine(Environment.NewLine + "Updating the employees name to Jonathan...");
    employeeNew.Name = "Jonathan";
    db.SubmitChanges();
    
  2. Next, add code to display the contents of the table again to see the change.

    ' Display the current list of Employees.
    Console.WriteLine("Employees:")
    For Each employee In employeeQuery
       Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder)
    Next
    
    // Display the current list of Employees.
    Console.WriteLine("Employees:");
    foreach (var employee in employeeQuery)
       Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder);
    

To delete a Modeling Services Folder and its contents

  1. Add the following code to remove the HumanResourcesExampleFolder Folder. This action also deletes the contents of the Folder, which in this case is the row in the [HumanResources].[Employees] table.

    ' Delete the HumanResourcesFolder Folder.
    Console.WriteLine(Environment.NewLine + "Deleting HumanResourcesFolder Folder...")
    Dim humanResourcesFolder As Folder
    humanResourcesFolder = _
           (From folder In foldersView _
            Where folder.Id = humanResourcesFolderId _
            Select folder).Single()
    foldersView.DeleteOnSubmit(humanResourcesFolder)
    db.SubmitChanges()
    
    // Delete the HumanResourcesFolder Folder.
    Console.WriteLine(Environment.NewLine + "Deleting HumanResourcesFolder Folder...");
    Folder humanResourcesFolder =
        (from folder in foldersView
         where folder.Id == (int)humanResourcesFolderId
         select folder).Single();
    foldersView.DeleteOnSubmit(humanResourcesFolder);
    db.SubmitChanges();
    
  2. Next, add code to display the contents of the table again to see the change. You should not see the employee row that was previously assigned to the HumanResourcesExampleFolder Folder.

    ' Display the current list of Employees.
    Console.WriteLine("Employees:")
    For Each employee In employeeQuery
       Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder)
    Next
    
    Console.WriteLine(Environment.NewLine + "Finished. Press any key.")
    
    // Display the current list of Employees.
    Console.WriteLine("Employees:");
    foreach (var employee in employeeQuery)
       Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder);
    
    Console.WriteLine(Environment.NewLine + "Finished. Press any key.");
    

To test the LINQ sample

  1. On the Build menu, click Build Solution.

  2. On the Debug menu, click Start Without Debugging.

  3. Observe the output in the console window.

Example

The following is the complete source code for the Main method of the RepAccess_LINQ project.

Imports System.Linq
Imports System.Data.Linq

Module Module1
   Sub Main()
      Try
         ' Create the DataContext object for the Repository. 
         Dim db As RepositoryDataContext = New RepositoryDataContext()

         ' Reference strongly typed tables for the [Repository.Item].[Folders]
         ' view and the [HumanResources].[Employees] table.
         Dim foldersView As Table(Of Folder) = db.Folders
         Dim employeesTable As Table(Of Employee) = db.Employees

         Dim humanResourcesFolderId As Long?

         ' Look to see if the target Modeling Services Folder already 
         ' exists by using the [Repository.Item].[PathsFolder] function.
         Console.WriteLine("Looking for the Repository/HumanResourcesFolder...")
         humanResourcesFolderId = db.PathsFolder("Repository/HumanResourcesFolder")

         ' If the target Folder does not exist, create it.
         If (humanResourcesFolderId.HasValue = False) Then
            ' First obtain the Folder for the system-defined "Repository" Folder.
            Dim folderRepository As Integer?
            folderRepository = _
               (From folder In foldersView _
               Where folder.Name = "Repository" _
               Select folder.Id).SingleOrDefault()

            If (folderRepository.HasValue) Then
               ' Create the new Folder and submit the changes.
               ' Refer to the identifier for the "Repository" Folder to make
               ' this new Folder a subFolder under Repository.
               Dim folderNew As Folder = New Folder()
               folderNew.Name = "HumanResourcesFolder"
               folderNew.ParentFolder = folderRepository

               foldersView.InsertOnSubmit(folderNew)

               db.SubmitChanges()

               ' Obtain the value of the inserted Folder
               humanResourcesFolderId = db.PathsFolder("Repository/HumanResourcesFolder")
            Else
               humanResourcesFolderId = 1
            End If
         End If

         Console.WriteLine("HumanResourcesExampleFolder: Id = {0}" + Environment.NewLine, humanResourcesFolderId.ToString())

         ' Create the new employee and submit the changes. Use the HumanResourcesFolder
         ' identifier for the Folder column of the Employee item.
         Console.WriteLine("Creating new employee: Name={0}", "John")
         Dim employeeNew As Employee = New Employee()
         employeeNew.Name = "John"
         employeeNew.Folder = humanResourcesFolderId

         employeesTable.InsertOnSubmit(employeeNew)

         db.SubmitChanges()

         Console.WriteLine("New employee: Id = {0}", employeeNew.Id)

         ' Display the current list of Employees.
         Console.WriteLine("Employees:")
         Dim employeeQuery = _
            From employee In employeesTable _
            Select employee

         For Each employee In employeeQuery
            Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder)
         Next

         ' Update the [HumanResources].[Employees] table.
         Console.WriteLine(Environment.NewLine + "Updating the employees name to Jonathan...")
         employeeNew.Name = "Jonathan"
         db.SubmitChanges()

         ' Display the current list of Employees.
         Console.WriteLine("Employees:")
         For Each employee In employeeQuery
            Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder)
         Next

         ' Delete the HumanResourcesFolder Folder.
         Console.WriteLine(Environment.NewLine + "Deleting HumanResourcesFolder Folder...")
         Dim humanResourcesFolder As Folder
         humanResourcesFolder = _
                (From folder In foldersView _
                 Where folder.Id = humanResourcesFolderId _
                 Select folder).Single()
         foldersView.DeleteOnSubmit(humanResourcesFolder)
         db.SubmitChanges()

         ' Display the current list of Employees.
         Console.WriteLine("Employees:")
         For Each employee In employeeQuery
            Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder)
         Next

         Console.WriteLine(Environment.NewLine + "Finished. Press any key.")

      Catch exception As Exception
         Console.WriteLine("An unexpected error occurred: {0}" & Environment.NewLine, exception.Message)
      Finally
         Console.ReadKey()
      End Try
   End Sub
End Module
using System;
using System.Linq;
using System.Data.Linq;

namespace RepAccess_LINQ
{
   class Program
   {
      static void Main(string[] args)
      {
         try
         {
            // Create the DataContext object for the Repository. 
            RepositoryDataContext db = new RepositoryDataContext();

            // Reference strongly typed tables for the [Repository.Item].[Folders]
            // view and the [HumanResources].[Employees] table.
            Table<Folder> foldersView = db.Folders;
            Table<Employee> employeesTable = db.Employees;

            long? humanResourcesFolderId;

            // Look to see if the target Modeling Services Folder already 
            // exists by using the [Repository.Item].[PathsFolder] function.
            Console.WriteLine("Looking for the Repository/HumanResourcesFolder...");
            humanResourcesFolderId = db.PathsFolder("Repository/HumanResourcesFolder");

            // If the target Folder does not exist, create it.
            if (humanResourcesFolderId.HasValue == false)
            {
               // First obtain the Folder for the system-defined "Repository" Folder.
               int? folderRepository =
                  (from folder in foldersView
                   where folder.Name == "Repository"
                   select folder.Id).SingleOrDefault();

               if (folderRepository.HasValue)
               {
                  // Create the new Folder and submit the changes.
                  // Refer to the identifier for the "Repository" Folder to make
                  // this new Folder a subFolder under Repository.
                  Folder folderNew = new Folder();
                  folderNew.Name = "HumanResourcesFolder";
                  folderNew.ParentFolder = (int)folderRepository;

                  foldersView.InsertOnSubmit(folderNew);

                  db.SubmitChanges();

                  // Obtain the value of the inserted Folder
                  humanResourcesFolderId = db.PathsFolder("Repository/HumanResourcesFolder");
               }
               else
                  humanResourcesFolderId = 1;
            }
            Console.WriteLine("HumanResourcesExampleFolder: Id = {0}" + Environment.NewLine, humanResourcesFolderId.ToString());

            // Create the new employee and submit the changes. Use the HumanResourcesFolder
            // identifier for the Folder column of the Employee item.
            Console.WriteLine("Creating new employee: Name={0}", "John");
            Employee employeeNew = new Employee();
            employeeNew.Name = "John";
            employeeNew.Folder = (int)humanResourcesFolderId;

            employeesTable.InsertOnSubmit(employeeNew);

            db.SubmitChanges();

            Console.WriteLine("New employee: Id = {0}", employeeNew.Id);

            // Display the current list of Employees.
            Console.WriteLine("Employees:");
            var employeeQuery =
                from employee in employeesTable
                select employee;

            foreach (var employee in employeeQuery)
               Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder);

            // Update the [HumanResources].[Employees] table.
            Console.WriteLine(Environment.NewLine + "Updating the employees name to Jonathan...");
            employeeNew.Name = "Jonathan";
            db.SubmitChanges();

            // Display the current list of Employees.
            Console.WriteLine("Employees:");
            foreach (var employee in employeeQuery)
               Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder);

            // Delete the HumanResourcesFolder Folder.
            Console.WriteLine(Environment.NewLine + "Deleting HumanResourcesFolder Folder...");
            Folder humanResourcesFolder =
                (from folder in foldersView
                 where folder.Id == (int)humanResourcesFolderId
                 select folder).Single();
            foldersView.DeleteOnSubmit(humanResourcesFolder);
            db.SubmitChanges();

            // Display the current list of Employees.
            Console.WriteLine("Employees:");
            foreach (var employee in employeeQuery)
               Console.WriteLine("Id = {0}, Name = {1}, Folder = {2}", employee.Id, employee.Name, employee.Folder);

            Console.WriteLine(Environment.NewLine + "Finished. Press any key.");
         }
         catch (Exception exception)
         {
            Console.WriteLine("An unexpected error occurred: {0}" + Environment.NewLine, exception.Message);
         }
         finally
         {
            Console.ReadKey();
         }
      }
   }
}

See Also

Other Resources

Loading Domain Models with Data
"Oslo" and Model-Driven Applications
The "M" Tool Chain