C H A P T E R  2

Working in Visual Studio

If you've ever had to replace your smart phone with a different make and model, it can be a real struggle getting to grips with something that you're unfamiliar with. For example, installing apps might be simple, but understanding how everything works beneath the surface could be quite obscure. Likewise, you might also choose to switch off Wi-Fi (or some other operation) by navigating through several levels of menus, because a more direct route isn't apparent.

In many ways, learning LightSwitch is a similar experience. Behind the point and click facade of the GUI, what actually happens behind the scenes? Are there easier ways to perform tasks that you can already achieve?

In this chapter, we'll unwrap LightSwitch and expose the inner workings of the product. You'll learn about the constituent projects that make up a LightSwitch solution and find out more about the role that SQL Server Express plays.

Switching to File View

The default view that's shown to you when working with LightSwitch is called Logical view. This basic view organizes a project into various folders such as Data Sources, Entities, and Screens. The Logical view enables you to add and edit items such as screens, queries, and data sources.

In addition to the Logical view, there is a second view called the File view. Knowing how to switch to this view is important if you want to undertake any serious LightSwitch development. This view allows you to see the various parts that make up a LightSwitch solution and enables you to work on individual projects. In addition, it allows you to add references to external DLLs in individual projects.

To switch to File view, use the drop-down in Solution Explorer and select the File View option, as shown in Figure 2-1.

images

Figure 2-1. Switching between Logical and File views

After switching to File view, you'll see a project listing. The toolbar within Solution Explorer includes a Show All Files button, as illustrated in Figure 2-2. Clicking this button displays all files that exist on the file system and reveals two additional projects, which are the ClientGenerated and ServerGenerated projects. With this option turned off, these projects are hidden along with a few other files, which include default.htm and Silverlight.js files.

images

Figure 2-2. Solution Explorer in File view

Figure 2-2 illustrates the projects that make up a LightSwitch solution. These include the following:

  • Client
  • ClientGenerated
  • Common
  • Server
  • ServerGenerated

In the following section, you'll discover what these projects actually do.

Root Folder Contents

If you examine the root folder of a LightSwitch project in Windows Explorer, you'll find subfolders that correspond to the projects that have been mentioned. You'll also find several other files that are needed to support your LightSwitch application.

_pvt_extensions Folder

A _pvt_extensions folder is created if any custom extensions are used in your project. This folder contains a subfolder for each extension that's used. For example, a LightSwitchFilter folder will be created if the LightSwitch filter extension is used in your project.

Silverlight.js

The Silverlight.js file is a JavaScript file that is automatically added to all Silverlight web applications. It contains various helper functions that support the use of Silverlight within the browser.

Default.htm

Default.htm is the web page that's used for hosting the Silverlight LightSwitch client. This file is used when an application is set to run as a web application. It's also used to load an out-of-browser (desktop) application. After the out-of-browser application is installed, this file is no longer needed for the application to run.

If you examine the contents of this file, you'll find JavaScript functions for performing various tasks. These include generating JavaScript alerts in case of errors, and pop-up alerts if the user attempts to navigate away from the web page without saving their changes.

ServiceConfiguration.cscfg

ServiceConfiguration.cscfg is an Azure configuration file, in XML format. This file is used for storing settings when applications are deployed to Windows Azure. If you're familiar with web development but unfamiliar with Azure, ServiceConfiguration.cscfg is analogous to the web.config file in an ASP.NET application. This file is important because it enables post deployment modification of settings through the Windows Azure portal. LightSwitch has added these because web.config cannot be edited in Azure without redeploying the whole application.

Listing 2-1 shows the default contents of the file. You'll find various settings here for configuring the tracing feature that is built into LightSwitch.

Listing 2-1. The Default Contents of the ServiceConfiguration.cscfg File

<ServiceConfiguration
    serviceName="Application1"
    xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
    <Role name="LightSwitchWebRole">
        <Instances count="1" />
        <ConfigurationSettings>
            <!-- A value of true will enable diagnostic logging on the server -->
            <Setting name="Microsoft.LightSwitch.Trace.Enabled" value="false" />
            <!-- A value of true only lets local access to Trace.axd -->
            <Setting name="Microsoft.LightSwitch.Trace.LocalOnly" value="true" />
            <!-- The valid values for the trace level are:

                None, Error, Warning, Information, Verbose -->
            <Setting name="Microsoft.LightSwitch.Trace.Level" value="Information" />
            <!-- True indicates that logging sensitive information is OK -->
            <Setting name="Microsoft.LightSwitch.Trace.Sensitive" value="false" />
            <!-This contains a semi-colon separated list

                of categories that will be enabled at the specifed trace level -->
            <Setting name="Microsoft.LightSwitch.Trace.Categories"
                value="Microsoft.LightSwitch" />

            <!-- True indicates http requests should be redirected to https -->
            <Setting name="Microsoft.LightSwitch.RequireEncryption" value="true" />
        </ConfigurationSettings>
        <Certificates>
        </Certificates>
    </Role>
</ServiceConfiguration>

ServiceDefinition.csdef

ServiceDefinition.csdef is an Azure configuration file. It contains the metadata used by the Windows Azure fabric and includes settings such as roles, service endpoints, and configuration settings.

A notable setting here is the vmsize attribute. This is used to control the size of the virtual machine when deployed to Azure. The price that you'll pay for hosting is directly related to this setting. By default, this is set to Small but can be manually changed to ExtraSmall if you want cheaper hosting. Table 2-1 illustrates the virtual machine options at the time of this writing.

image

image

Listing 2-2 shows the default contents of the ServiceDefinition.csdef file. You'll see the elements that relate to configuration settings, bindings, endpoints, and certificates.

Listing 2-2. ServiceDefinition.cscfg File

<ServiceDefinition
     name="Application1"
     xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
    <WebRole name="LightSwitchWebRole"
             vmsize="Small"
             enableNativeCodeExecution="true">
        <ConfigurationSettings>
            <Setting name="Microsoft.LightSwitch.Trace.Enabled" />
            <Setting name="Microsoft.LightSwitch.Trace.LocalOnly" />
            <Setting name="Microsoft.LightSwitch.Trace.Level" />
            <Setting name="Microsoft.LightSwitch.Trace.Sensitive" />
            <Setting name="Microsoft.LightSwitch.Trace.Categories" />
            <Setting name="Microsoft.LightSwitch.RequireEncryption" />
        </ConfigurationSettings>
        <Sites>
            <Site name="Web">
                <Bindings>
                    <Binding name="HttpIn" endpointName="HttpIn" />
                    <Binding name="HttpsIn" endpointName="HttpsIn" />
                </Bindings>
            </Site>
        </Sites>  
        <Endpoints>
            <InputEndpoint name="HttpIn" protocol="http" port="80" />
            <InputEndpoint name="HttpsIn" protocol="https" port="443"
                 certificate="SSLCertificate" />
        </Endpoints>
        <Certificates>
            <Certificate name="SSLCertificate" storeLocation="LocalMachine"
                 storeName="My" />
        </Certificates>
    </WebRole>
</ServiceDefinition>

GeneratedArtifacts Folder

In several of the LightSwitch projects, you'll find folders called GeneratedArtifacts. These folders contain code that is autogenerated by LightSwitch.

ApplicationDefinition.lsml File

The ApplicationDefinition.lsml (LightSwitch Markup Language) file (mentioned in Chapter 1) is the most important file in LightSwitch. The definition and details of screens and queries are defined in this file. You'll find this file in the Data folder.

All other projects in the solution reference this file. Figure 2-3 shows the ApplicationDefinition.lsml file in the Data folder, and a reference to it in the Server project.

images

Figure 2-3. References to ApplicationDefinition.lsml in other projects

Because the ApplicationDefinition.lsml file contains so much content, it often causes contention when multiple developers are working together on a project through source control.

Although the official recommendation is not to manually edit this file, there are some features and fixes that can be performed only through a manual edit. Cloning a LightSwitch screen is one example requiring you to manually edit the LSML. We strongly recommend that you close out of LightSwitch and back up the LSML file before editing.

To illustrate the LSML, we'll create an application that contains a Customers table and three screens based on the search, create, and detail templates. Listing 2-3 shows an outline of the LSML file that is generated.

Listing 2-3. Contents of ApplicationDefinition.lsml File

<?xml version="1.0" encoding="utf-8" ?>
<ModelFragment xmlns="http://schemas.microsoft.com/LightSwitch/2010/xaml/model"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Application Name="LightSwitchApplication"
               Version="1.0.0.0"
               DefaultNavigationItem="!module/NavigationItems[Tasks]"
               Shell=":Standard"
               Theme=":Blue">
  </Application>

  <EntityContainerGroup Name="DataWorkspace">
   </EntityContainerGroup>

  <EntityContainer Name="ApplicationData" IsIntrinsic="True">
    <SubmitOperation Name="SaveChanges" />

    <EntitySet CanDelete="True"
               CanInsert="True"
               CanUpdate="True"
               EntityType="Customer"
               Name=" Customers" />
  
    <QueryOperation Name=" Customers_Single"
                    ReturnType=" Customer">
    </QueryOperation>
  
    <QueryOperation Name=" Customers_SingleOrDefault"
                    ReturnType="Customer">
    </QueryOperation>
  
    <QueryOperation Name="Customers_All"
                    ReturnType="Customer*">
    </QueryOperation>
  </EntityContainer>
  
  <DataService DataProvider="EntityFrameworkDataProvider"
               EntityContainer="ApplicationData"
               Name="ApplicationDataMapping" />

  <EntityType Name="Customer">
….  
</EntityType>
  <Screen Name="CustomerDetail">
….
</Screen>

  <Screen LaunchMode="Multiple" Name="CreateNewCustomer">
….
</Screen>

  <Screen Name="SearchCustomers">
….
</Screen>

</ModelFragment

In Chapter 1, you learned about the model-based architecture behind LightSwitch. You may recognize that the XML elements in this file correspond to the LightSwitch building blocks that were described in that chapter.

The Application element contains the details that relate to the client application such as shell, theme, and menu navigation contents.

You'll find an EntityContainer element for each of the data sources in your application. The IsIntrinsic attribute indicates to LightSwitch that the specified database is the intrinsic database. This is the database that is defined by, and deployed with, your LightSwitch application.

Within this element, you'll find EntitySet elements for each table. QueryOperation elements define the operations for retrieving records from a given entity set.

An EntityType element exists for each table, and child elements define the columns and data types within the table.

Finally, the contents of screens are saved in Screen elements. If you've ever closed out of the screen designer without saving changes, you would have been prompted to save your changes to the ApplicationDefinition.lsml file. The reason you receive this dialog box is that the screen details are contained in the screen elements of the LSML.

Creating Nested Navigation Groups

Here's an example of where you might want to manually modify the LSML file. Out of the box, LightSwitch doesn't support the notion of nested navigation groups. Navigation groups are used by LightSwitch shells to present the UI for launching screens. To overcome this limitation, you can manually modify the LSML to create a nested navigation menu.

The navigation hierarchy is defined in the Application section of the LSML. Listing 2-4 shows an outline of this section.

Listing 2-4. Outline of the LSML Application Section

  <Application Name="LightSwitchApplication"
               Version="1.0.0.0"
               DefaultNavigationItem="!module/NavigationItems[Tasks]"
               Shell=":Standard"
               Theme=":Blue">
    <Application.Methods>
      <ApplicationMethod Name="ShowCustomerDetail">
        <ApplicationMethod.Attributes>
          <ShowScreenMethod TargetScreen="CustomerDetail" />
        </ApplicationMethod.Attributes>
        <ApplicationMethodParameter Name="CustomerId"
                                    ParameterType=":Int32" />
      </ApplicationMethod>

    <!--Comment - Additional <Application.Methods> elements
               appear here for each screen-->

    <Application.NavigationItems>
            <!--Comment - Navigation items appear here  - further details in Listing 2-5-->

    </Application.NavigationItems>

<!--Comment - ApplicationCommand elelments are the 'links' for opening new screensimage

    <ApplicationCommand Name="ScreenCommandShowCreateNewCustomer"
                        Target="!module/Methods[ShowCreateNewCustomer]" />
    <ApplicationCommand Name="ScreenCommandShowSearchCustomer"
                        Target="!module/Methods[ShowSearchCustomer]" />
  </Application>

You'll find multiple <Application.Method> elements for each screen in your application. Toward the end of the <Application> element, the ApplicationCommand elements point to the methods that are defined earlier.

The important part that defines the navigation hierarchy belongs inside the <Application.NavigationItems> element. Listing 2-5 shows the snippet LSML that you would use to create a nested hierarchy. In this example, Group1 and Group3 are top-level groups. Group2 is a child of Group1.

Listing 2-5. LSML Fragment for Creating Nested Navigation Groups

<Application.NavigationItems>
  <ApplicationNavigationGroup Name="Group1">
    <ApplicationNavigationGroup.Attributes>
      <DisplayName Value="Main Group 1" />
    </ApplicationNavigationGroup.Attributes>

    <ApplicationNavigationGroup Name="Group2">
      <ApplicationNavigationGroup.Attributes>
        <DisplayName Value=" Group 1 SubMenu" />
      </ApplicationNavigationGroup.Attributes>
      <ApplicationNavigationLink
          Command="!module/Commands[ScreenCommandShowCreateNewCustomer]"
          Name="link2" />
    </ApplicationNavigationGroup>
  </ApplicationNavigationGroup>

  <ApplicationNavigationGroup Name="Group3">
    <ApplicationNavigationGroup.Attributes>
      <DisplayName Value="Main Group 2" />
    </ApplicationNavigationGroup.Attributes>
    <ApplicationNavigationLink
        Command="!module/Commands[ScreenCommandShowSearchCustomer]"
        Name="link3" />
  </ApplicationNavigationGroup>

</Application.NavigationItems>

The <ApplicationNavigationGroup> element defines a navigation group. Tasks and Administration are groups that appear by default in a LightSwitch application. These <ApplicationNavigationGroup> elements can be nested inside each other to create a nested hierarchy. Figure 2-4 shows a more realistic example of what a nested navigation group would look like.

images

Figure 2-4. Nested navigation group

In this illustration, Products and Customers are children of the Tasks group. The Products group contains the child groups Food Items and Non Food Items. If you collapse a parent group, all child groups are collapsed at the same time. For example, collapsing Products hides both the Food Items and Non Food Items groups.

Although this technique works against the standard LightSwitch shell, it isn't guaranteed to work against other third-party shells.

The important point about this demonstration is that it introduces you to the contents of the LSML file and provides an example of why you might want to manually edit it.

Server Project

The Server project is a full .NET 4.0 class library and contains the logic that is executed on the server. Any code that you've written to handle data source events and validation logic is added to this project.

As soon as you write some code that handles a data source event against a table in your intrinsic database, a UserCode folder is created. Your code is then placed inside a file called ApplicationDataService.vb or ApplicationDataService.cs, depending on your chosen language.

If you were to attach to an external database called Northwind and write some code to handle a data source event for a table in the Northwind database, this code would be created in a file called NorthwindDataService.vb or NorthwindDataService.cs. As you saw in Chapter 1, a data service is created for each data source in your application. This explains why the term DataService in used in the file names. The event-handling code that you write for any entity in a data source is saved in a single data service file.

Examples of data source events are the events that make up the save pipeline. These are shown in the following list.

  • Deleted
  • Deleting
  • Inserted
  • Inserting
  • Updated
  • Updating
  • Validating

Server access control events such as CanDelete, CanInsert, and CanRead are also saved in the DataService file. The query method code that you write to handle events in the query pipeline such as PreprocessQuery will also find itself in the file.

You can also use the ServerGenerated project to store various application settings. In Chapter 14, you'll learn how to send emails from the server. Rather than hard-coding the SMTP server address into your code, the address can be stored in a settings file, which makes it possible to change this setting after deployment.

ServerGenerated Project

The ServerGenerated project is an ASP.NET 4.0 that's executed on the server. You'll find a web.config file in this project that contains the connection string to your intrinsic database.

The files that support the Entity Framework model are also autogenerated into this folder. These include the files ApplicationData.ssdl, ApplicationData.csdl, and ApplicationData.msl. You'll also find .MSL, .CSDL, and .SSDL files for each additional data source that is defined in your application.

SSDL stands for Store Schema Definition Language and defines the schema of the tables at a SQL Server level. CSDL stands for Conceptual Schema Definition Language, and this defines the entities and relationships that are visible to LightSwitch.

In LightSwitch, there is always a one-to-one relationship between entities and tables. However, the Entity Framework allows for more-complex mappings, and a mapping layer defines the relationship between the conceptual and logical store layers. These mappings are stored in an MSL file, which stands for Mapping Schema Language. Figure 2-5 illustrates the relationships between CSDL, MSL, and SSDL files.

images

Figure 2-5. The relationships between conceptual, mapping, and store layers

Client Project

The client project is a Silverlight 4.0 class library project. It contains the client-side business logic that's executed on the client. For example, if you write some code to handle a button click, the code ends up in this project. Because this is a Silverlight project, only references to Silverlight DLLs can be added to this project.

As soon as you write any screen-related code, a UserCode folder is created and the code's file is placed inside this folder. If you create a Customer Detail screen, for example, any code that you write is added into a file called CustomerDetail.vb (or CustomerDetail.cs). Separate screen code files are generated for each screen, with file names that match the name of the screen. If a screen is renamed, LightSwitch automatically renames the underlying screen code file. The screen code file contains the user code that you write to handle the following screen events:

  • Activated
  • Closing
  • Created
  • InitializeDataWorkspace
  • Run
  • SaveError
  • Saved
  • Saving

The Client project also contains a file called Application.vb (or Application.cs). This Application file contains the user code that you would write to control security. For example, if a CustomerDetail_CanRun method is created to control who can access the screen, this method is saved into the Application code file.

ClientGenerated Project

The ClientGenerated project is a Silverlight 4.0 application project. The main purpose of this project is to create a Silverlight XAP file.

An XAP file is a Silverlight Application Package and contains a compiled Silverlight application. Just like the Microsoft Office DOCX and XLSX files, XAP files are zip files that contain the files that are needed for the LightSwitch application to run. Renaming a XAP file to ZIP and opening it reveals the content.

After building a LightSwitch application, you can find the XAP file in the inReleaseWeb or inDebugWeb directory, depending on the build type. Assuming that you've called your LightSwitch application OfficeCentral, the file will be named OfficeCentral.Client.Xap. The XAP file contains the DLLs that are built from the Client and ClientGenerated projects, dependent DLLs, the LSML file, and an XAML file containing the shell definition.

Another important file that you'll find inside the XAP file is the AppManifest.xaml file. This file defines the DLLs that are included in the XAP. Listing 2-6 illustrates an example AppManifest file. The EntryPointAssembly attribute indicates that Microsoft.LightSwitch.Client.Internal.dll is the main assembly for the application. An instance of the Microsoft.LightSwitch.Runtime.Shell.Implementation.App class is instantiated when your LightSwitch application starts. The RuntimeVersion attribute defines the Silverlight version the application is built for, and the remainder of the file defines associated DLL files.

Listing 2-6. Contents of AppManifest.xaml

<Deployment
    xmlns="http://schemas.microsoft.com/client/2007/deployment"
    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
    EntryPointAssembly="Microsoft.LightSwitch.Client.Internal"
    EntryPointType="Microsoft.LightSwitch.Runtime.Shell.Implementation.App"
   RuntimeVersion="4.0.50826.0">
  <Deployment.Parts>
    <AssemblyPart x:Name=" OfficeCentral.ClientGenerated"
        Source=" OfficeCentral.ClientGenerated.dll" />
    <AssemblyPart x:Name="Application.Common" Source="Application.Common.dll" />
    <AssemblyPart x:Name=" OfficeCentral.Client" Source=" OfficeCentral.Client.dll" />
    <AssemblyPart x:Name="Microsoft.LightSwitch.Base.Client"
         Source="Microsoft.LightSwitch.Base.Client.dll" />
    <AssemblyPart x:Name="Microsoft.LightSwitch.Client"
         Source="Microsoft.LightSwitch.Client.dll" />
.........
  </Deployment.Parts>
</Deployment>

The ClientGenerated project can be used to make resources available to the client. In Chapter 11, you'll learn how to create reports by using Microsoft Word automation. A DOT Word template file provides the template on which the report is based. The ClientGenerated project is the mechanism that enables the DOT file to be distributed to the client.

Common Project

The Common project contains code that's executed on both the client and server. This project is a plain Silverlight 4.0 class library project. However, the initial assembly references are set to those belonging in the portable class library subset.

Portable class libraries were introduced in .NET 4.0. These types of libraries can run on multiple .NET Framework platforms. In LightSwitch, the assembly built from the Common project is called from both the Silverlight client and ASP.NET server applications.

You'll find a UserCode folder in the Common project. This folder contains the user code that you write for each entity. For example, the Created, Changed, and Compute methods are saved here. The GeneratedArtifacts folder contains a series of autogenerated code for each entity.

SQL Server

SQL Server plays a major role in LightSwitch. This section shows you where your data is saved and why SQL Server Express is required, examines some of the inner workings of user instances, and describes how you can diagnose issues by using SQL Profiler.

Where Is the Intrinsic Database?

When you create a new LightSwitch project, an intrinsic database called ApplicationData is created in the project folder. This data source is the default place where user tables are created. The LightSwitch security tables containing users and roles are also created here. You'll find the database file at bindataApplicationData.mdf.

If you're not too familiar with SQL Server, the MDF file is the primary file that is used for storing the data and database objects. Tables, views, indexes, constraints, and stored procedures are examples of the types of objects that are stored in the MDF file. When debugging applications, an ApplicationData.ldf file is created in the same directory as the MDF file. The LDF file contains the contents of the SQL Server transaction log.

images Caution This intrinsic database is designed to store temporary data for use during debugging time. This data is not deployed with the application, and there may be times when the LightSwitch IDE has to delete the data in order to achieve a schema change.

Why Do I Need SQL Express?

Some users may prefer to host the intrinsic database by using a non-Express version of SQL Server, particularly if a full version of SQL Server is available on the local development machine. This scenario is not supported, and errors will occur if you modify the database connection string in the web.config file to point to a non–SQL Express instance. SQL Express is required so that LightSwitch projects can be shared between users. By using the Auto Attach feature of SQL Express, both the database and LightSwitch project files are self-contained in a single folder. This allows you to easily back up and share your LightSwitch project.

Note that the SQL Server Express requirement does not apply to deployed applications. During deployment, you can choose to host the intrinsic database in a full version of SQL Server, SQL Express, or even SQL Server Azure if you wish.

What Is a SQL Server User Instance?

Unfortunately, many LightSwitch developers first encounter the term SQL user instance following a failure to connect to the intrinsic database. In order to explain what this is, we'll describe the problems that user instances were designed to solve.

In simple terms, an instance is a copy of SQL Server that runs on a machine. Each instance has its own settings and logins, and listens on a distinct port number.

The usual way of accessing the contents of a SQL Server database file is to first attach it in SQL Server. If you're using an edition of SQL Server other than SQL Server Express, this step must be carried out. After you do this, a security login must be created, and that login added to the user list for the database. For developers, this is a cumbersome process. To make life easier, SQL Server Express includes an Auto Attach feature. This allows you to use a SQL Express database, just by specifying a database file name in the connection string. There's no need for you to do anything else in SQL Server Management Studio, or to carry out any additional setup tasks. This feature makes it really easy for you to use databases and share them with others.

The traditional way of attaching a database can present a second challenge. This is because you must have SQL Server administrative privileges to attach a database. The exact problem is that you might not be an administrator, or you might work in a corporate environment where you've been denied the necessary permissions. User instances provide the solution to these problems. They allow you to auto-attach a database without needing any administrative permissions. This feature is found only in the Express version and isn't available in any other edition of SQL Server.

A user instance is like a normal instance, but is created on demand when a connection to the database is first made. The user instance runs under the security context of the user who initiates the connection. This therefore gives the user full administrative control over the instance, even if the user doesn't have administrative privileges on the machine.

User instances are hosted by a parent SQL Server Express instance. If you want to use a user instance, you'd create a connection to the parent SQL Server Express instance and specify the user instance flag in the connection string.

images Tip Chapter 17 contains various tips to help you diagnose and solve SQL Server problems.

Attaching the SQL Server Intrinsic Database by Using Server Explorer

In this section, we'll show you how to use Server Explorer to connect to your intrinsic database. By connecting to the database in this way, you can work with data inside of Visual Studio without having to run your application.

You can also create database diagrams that enable you to view multiple tables and relationships in your database. This allows you to see the bigger picture, because the LightSwitch designer lets you view only one table at a time.

In order to view the intrinsic database in Server Explorer, open Server Explorer by clicking View image Server Explorer, or click Ctrl+Alt+S. After Server Explorer appears, right-click the Data Connections icon and select the Add Connection option, as shown in Figure 2-6. The Add Connection dialog box appears (see Figure 2-7).

images

Figure 2-6. In the Server Explorer window, choose the Add Connection option

images

Figure 2-7. The Add Connection dialog box

In the Add Connection dialog box, enter the SQL Server Express instance name into the Server Name text box. Select the option to Attach a Database File and provide the path to your ApplicationDatabase.mdf file. Now click the Advanced button, and in the Advanced Properties dialog box, set the User Instance option to True, as shown in Figure 2-8.

images

Figure 2-8. Set the User Instance option to True.

Complete the steps in the Add Connection dialog box. When you are finished, the connection to your intrinsic database will be shown in Server Explorer, as you can see in Figure 2-9.

images

Figure 2-9. The ApplicationDatabase file now appears in Server Explorer.

Notice how all of the database objects are visible beneath the Tables node. You'll also see a set of aspnet_* tables. These tables are used by LightSwitch to manage security, users, and roles.

By using the options that appear in the Database Diagrams node, you can create and manage your own database diagrams.

It's important to bear in mind that additional tables or columns added through Server Manager will not be reflected in your LightSwitch model. Therefore, you should continue to design your tables by using the LightSwitch table designer.

images Note When the time comes to deploy your application, you might want to include the data that you've entered at debugging time. For example, you might want to script out the data that you've entered so that you can add it to your deployment package. Attaching the database allows you to get to your data and to carry out this task..

Profiling the Intrinsic Database by Using SQL Server Profiler

SQL Server Profiler is a very useful debugging tool. It allows you to see the exact SQL that LightSwitch generates and submits to SQL Server. You'll find it included in some of the paid-for versions of SQL Server. If you don't have access to SQL Server Profiler, a free alternative is AnjLab SQLExpressProfiler. This product is open source, and you can download it from http://sites.google.com/site/sqlprofiler/.

SQL Server Profiler can help you uncover some of the inner workings of LightSwitch. We'll show you how to use Profiler now because we'll refer to the traces that it creates later in the book.

During debugging time, LightSwitch hosts the intrinsic database by using a user instance of SQL Server Express. If you want to start a trace in Profiler, you can't connect to a SQL Server user instance by using TCP/IP and a server name. Instead, you have to use named pipes. To find out the address to use, connect to SQL Server Express by using Management Studio, or by using Server Explorer as described earlier.

If you're using Server Explorer, create a new connection to the master database of your SQLEXPRESS instance. Now start your LightSwitch application. Next, create a new query by choosing Data image New Query. Execute the SQL command shown in Listing 2-7 to return the pipe name, as shown in Figure 2-10.

Listing 2-7. SQL to Find Out the Pipe Name

SELECT owning_principal_name,instance_pipe_name FROM sys.dm_os_child_instances
images

Figure 2-10. The pipe name is shown in the results.

Now that you know the pipe name, you can use SQL Server Profiler to trace your intrinsic database. Connect to the server by using the pipe name (shown in Figure 2-11) and begin a trace. Perform some actions in your LightSwitch application, and the results will be shown in the trace (see Figure 2-12).

images

Figure 2-11. Using named pipes to connect to SQL Profiler

images

Figure 2-12. Illustration of trace results

Debugging LightSwitch Code

Even the best programmers will make mistakes when writing applications. Fortunately, the Visual Studio IDE contains some powerful tools that will help you detect and correct problems.

You may have some familiarity using the debugger. If not, this section will help you understand some of the basics before moving on further into this book.

Debugging Concepts

Breakpoints are a key part of debugging. You can insert these into your code by clicking on the left margin of the code window. When the code execution reaches the breakpoint, the program stops executing temporarily. You can then step through the remaining code one line at a time by pressing F10, or by clicking the Step Over button. If you want to dive into functions or subprocedures that are being called in the current line, pressing F11 allows you to Step Into the child procedures.

If you want to skip over several lines of code without having to step over each line individually, you can place the cursor on a line beneath and select the Run to Cursor option, as shown in Figure 2-13.

images

Figure 2-13. Using the Run to Cursor option

If during a session you want to run your application for a while without stopping at breakpoints, you can select the Disable All Breakpoints option under the Debug menu. When you're ready to break into breakpoints again, you can select the Enable All Breakpoints option to continue.

Locals Window

The Locals window, shown in Figure 2-14, allows you to keep track of local variables. These variables appear beneath the Name column, and additional attributes can be shown by expanding the tree nodes.

images

Figure 2-14. Local variables shown in the Locals window

Autos and Watch Windows

The Autos window is one of the main windows used during debugging. This window displays the values of variables and properties as they are evaluated by the compiler. These values disappear when the objects fall out of scope.

Unlike the Autos window, the Watch window allows you to view values throughout the execution of a program. Figure 2-15 illustrates how a watch can be added through the Autos window by selecting the Add Watch option.

images

Figure 2-15. Adding a watch via the Autos window

Immediate and Command Windows

The Immediate window, shown in Figure 2-16, is a very versatile tool. It allows you to easily interrogate variable values by using the ? operator. The Immediate window provides IntelliSense assistance to help you construct the correct syntax. Unlike the other debugging windows, the Immediate window allows you to change the values of properties and variables while debugging.

images

Figure 2-16. Using the ? command in the Immediate window

The Command window, shown in Figure 2-17, allows you to run Visual Studio commands such as File.SaveAll. You don't need to be in debug mode to run commands in the Command window. As in the Immediate window, the commands in the Command window also support IntelliSense.

images

Figure 2-17. Command window

While in the Command window, you can switch to the Immediate window by typing immed. Conversely, you can switch to the Command window from the Immediate window by typing cmd.

Attaching to the Debugger

The Debug image Attach to Process menu option allows you to attach processes to the debugger. For example, if you want to debug using the Firefox browser instead of Internet Explorer, you can attach the Firefox Silverlight client to the debugger by attaching to the plugin-container.exe (type Silverlight) process. This is shown in Figure 2-18.

images

Figure 2-18. Attaching processes to the debugger

Debugging Queries

Experienced developers will often extend queries by using the _PreProcessQuery or _Executed methods. When LINQ or other coding errors are encountered, these exceptions will be swallowed by LightSwitch. A red cross appears against any grids that are bound to the query, and no indication is given as to what the exact cause of the error might be.

To help diagnose such errors, failed queries raise the _ExecuteFailed event, giving access to the underlying exception. Handling this event and placing a breakpoint on the method (Figure 2-19) allows you to interrogate the exception by using tools such as the Immediate or Autos windows.

images

Figure 2-19. Handling _ExecuteFailed

Debugging Threading Issues

Let's imagine that you've written a complex piece of screen code. This code performs an operation that takes a long time to complete. When your code runs, your application still remains responsive. In other words, it can still respond to mouse clicks and keystrokes, and provides a positive experience for the user. Your application can do this because LightSwitch uses two threads.

In LightSwitch, all UI tasks and user interaction is carried out by a UI thread (also known as the main dispatcher). Each screen gets its own thread for carrying out tasks that are not UI related. This thread is called the screen thread, or logic thread. Whenever you write any user code on a screen, the operation is executed on the screen thread by default.

Let's say that you want to perform a task that requires some user intervention. For example, imagine that you want to show a File Open dialog box. You must write code to specifically carry out this task on the UI thread. If you fail to do this, LightSwitch throws an exception.

If you're debugging a piece of code, it's really useful to be able to identify what thread you're running on. To find this out, place a breakpoint in your code. You can then use the Immediate window and call the CheckAccess method, as shown in Listing 2-8. If the result is true, your code is running on the UI thread. If false, it's running on the logic thread.

Listing 2-8. CheckAccess Method

Microsoft.LightSwitch.Threading.Dispatchers.Main.CheckAccess()

There are three dispatchers that you can use in LightSwitch. These allow you to execute code on a different thread. The following list summarizes the LightSwitch object that you can use to reference the dispatcher.

  • Main dispatcher (UI thread)—Dispatchers.Main
  • Screen dispatcher (logic thread)—Screen.Details.Dispatcher
  • Application dispatcher—Application.Details.Dispatcher

In addition to the UI and logic dispatchers, the application dispatcher is responsible for running global application code that isn't associated with any specific screen.

images Note If you need to diagnose problems after deployment, the tracing feature in LightSwitch can help you to do that. You can find out more about this in Chapter 17.

Compacting LS Solutions for Backup

You may have discovered that LightSwitch projects take up a lot of space on the file system. The size taken up by an empty project is around 89MB. After building the project for the first time, the size increases to around 132MB, even though there are still no tables or screens in the project.

The size of LightSwitch projects can present a problem when trying to back up or share your work with others. Because the bin and obj folders are regenerated following each build, these folders can be deleted prior to backing up. If you choose to do this, however, make sure not to delete the file bindataApplicationData.mdf, because this contains your design-time intrinsic database.

You can simplify this task by creating a batch file to automate the process. The content of such a script is shown in Listing 2-9.

Listing 2-9. Batch File to Compact Solution

rd /q /s BinDebug
rd /q /s BinRelease

rd /q /s ClientBinDebug
rd /q /s ClientBinRelease

rd /q /s ClientobjDebug
rd /q /s ClientobjRelease

rd /q /s ClientGeneratedBinDebug
rd /q /s ClientGeneratedBinRelease

rd /q /s ClientGeneratedobjDebug
rd /q /s ClientGeneratedobjRelease

rd /q /s CommonBinDebug
rd /q /s CommonBinRelease

rd /q /s CommonobjDebug
rd /q /s CommonobjRelease

rd /q /s ServerBinDebug
rd /q /s ServerBinRelease

rd /q /s ServerobjDebug
rd /q /s ServerobjRelease

rd /q /s ServerGeneratedinDebug
rd /q /s ServerGeneratedinRelease
rd /q /s ServerGeneratedin

rd /q /s ServerGeneratedobjDebug
rd /q /s ServerGeneratedobjRelease

Create this file in the root folder of your project and execute it in order to delete all extraneous files. The remaining files and folders can be zipped into a compressed file to further reduce file size.

Summary

This chapter has covered the following topics:

  • How LightSwitch projects are organized on the file system
  • The purpose of the LSML file
  • The role that SQL Server Express plays in LightSwitch
  • How to debug LightSwitch code

You can switch your LightSwitch project into File view by clicking a button in Solution Explorer. This reveals the projects that make up a LightSwitch solution. The projects that you'll find are as follows:

  • Client contains the client-side business logic.
  • ClientGenerated builds the Silverlight XAP file.
  • Server contains server-side business logic.
  • ServerGenerated contains the ASP.NET server project.
  • Common contains the common business logic used on the client and server.

ApplicationDefinition.lsml is a very important file and contains the definitions of all screens and entities in your application. In some advanced scenarios, you'll need to manually modify this file by using a text editor. The example that we've given in this chapter shows you how to create nested navigation groups. Whenever you modify this file outside of LightSwitch, we strongly recommend that you back up the file.

The intrinsic database stores the tables that you create in LightSwitch. During design time, a temporary database is created in the location bindataApplicationData.mdf. This temporary database is used to store your data between debugging sessions. The data that you enter at design time won't be deployed with your final application. If you need to get to this data, you can connect to the ApplicationData.mdf file by using Server Explorer or SQL Server Management Studio.

The intrinsic database must be hosted by SQL Server Express at development time (although there isn't any limitation for deployed applications). The SQL Server Express requirement makes it easy for you to share LightSwitch projects. If someone else opens a project that you've created, there isn't any need for them to create or attach a corresponding database. The auto-attach, and user instance features of SQL Server Express make this possible.

Finally, you've seen how to debug LightSwitch applications by using the debugger. When you're debugging problems with queries, it's a good idea to place a breakpoint in the ExecuteFailed method. This allows you to get to the actual exception. When debugging threading issues, you can call the CheckAccess method on the main dispatcher to work out what thread you're running on.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.55.18