BusinessRx Community

Dedicated to the advancement of software, technology and the people who devote their lives to it.

Welcome to BusinessRx Community Sign in | Join | Help
in Search

BusinessRx Reading List

These blog entries are written by industry experts and leaders. We consider this content to be a good read for any software developer or web technologist.

Browse by Tags

All Tags » Visual Studio » Data   (RSS)

  • LINQ to SQL (Part 7 - Updating our Database using Stored Procedures)

    Over the last few weeks I've been writing a series of blog posts that cover LINQ to SQL.  LINQ to SQL is a built-in O/RM (object relational mapper) that ships in the .NET Framework 3.5 release, and which enables you to model relational databases using .NET classes.  You can use LINQ expressions to query the database with them, as well as update/insert/delete data.

    Below are the first six parts in this series:

    In part 6 I demonstrated how you can optionally use database stored procedures (SPROCs) and user defined functions (UDFs) to query and retrieve data using your LINQ to SQL data model. In today's blog post I'm going to discuss how you can also optionally use SPROCs to update/insert/delete data from the database.

    To help illustrate this - let's start from scratch and build-up a data access layer for the Northwind sample database:

    Step 1: Creating our Data Access Layer (without using SPROCs yet)

    In my Part 2: Defining our Data Model Classes tutorial I discussed how to use the LINQ to SQL ORM designer that is built-in to VS 2008 to create a LINQ to SQL class model like below:

    Adding Validation Rules to our Data Model Classes

    After defining our data model classes and relationships we'll want to add some business logic validation to our data model.  We can do this by adding partial classes to our project that add validation rules to our data model classes (I cover how to-do this in-depth in my Part 4: Updating our Database LINQ to SQL tutorial).

    For example, we could add validation rules to enforce that the Customer's phone number follows a valid phone pattern, and that we don't add Orders where the customer's RequiredDate for delivery is before the actual OrderDate of the Order.  Once defined in partial classes like below, these validation methods will automatically be enforced anytime we write code to update our data model objects in an application.

    VB:

    C#:

     

    Adding a GetCustomer() Helper Method to our DataContext

    Now that we have our data model classes created, and have applied validation rules to them, we can query and interact with the data.  We can do this by writing LINQ expressions against our data model classes to query the database and populate them (I cover how to-do this in my Part 3: Querying our Database LINQ to SQL tutorial).  Alternatively we could map SPROCs to our DataContext and use them to populate the data model classes (I cover how to-do this in my Part 6: Retrieving Data using Stored Procedures LINQ to SQL tutorial).

    When building a LINQ to SQL data layer you'll usually want to encapsulate common LINQ queries (or SPROC invocations) into helper methods that you add to your DataContext class.  We can do this by adding a partial class to our project.  For example, we could add a helper method called "GetCustomer()" that enables us to lookup and retrieve a Customer object from the database based on their CustomerID value:

    VB:

    C#:

     

    Step 2: Using our Data Access Layer (still without SPROCs)

    We now have a data access layer that encapsulates our data model, integrates business validation rules, and enables us to query, update, insert, and delete the data.

    Let's look at a simple scenario using it where we retrieve an existing customer object, update the customer's ContactName and Phone Number, and then create a new Order object and associate it with them.  We can write the below code to do all of this within a single transaction.  LINQ to SQL will ensure that our business logic validation rules are clean before saving anything in the database:

    VB:

    C#:

    LINQ to SQL monitors the modifications we make to the objects we retrieve from the DataContext, and keeps track of all of the objects we add into it.  When we call DataContext.SubmitChanges() at the end, LINQ to SQL will check that our business logic rules are valid, and if so automatically generate the appropriate dynamic SQL to update our Customer record above, and insert a new record into the Orders table. 

    Hang on a second - I thought this post was about using SPROCs??? 

    If you are still reading this, you might be feeling confused about where SPROCs fit into this post.  Why did I show you above how to write code that works with our data model objects, and then causes dynamic SQL to run?  Why haven't I showed you how to call a SPROC for doing inserts/updates/deletes instead yet? 

    The reason is that the programming model in LINQ to SQL for working with data model objects backed by SPROCs is the same as those updated via dynamic SQL.  The way you add data model validation logic is exactly the same (so all the validation rules on our data model classes above still apply when we use SPROCs).  The code snippet above where we use our data access layer to retrieve a customer, update it, and then add a new order associated with it is also exactly the same regardless of whether we are using dynamic SQL for updates, or whether we have configured our data model classes to use SPROCs instead.

    This programming model symmetry is powerful both in that you don't have to learn two ways of doing things, and also because it means that you don't have to decide up front at the beginning of your project whether you are going to use SPROCs or not.  You can start off using the dynamic SQL support provided by the LINQ to SQL ORM for all queries, inserts, updates and deletes.  You can then add your business and validation rules to your model.  And then later you can optionally update your data mapping model to use SPROCs - or not if you decide you don't want to.   The code and tests you write against your data model classes can stay the same regardless of whether you use dynamic SQL or SPROCs.

    We'll now spend the rest of this blog post demonstrating how we can update the data model we've built to use SPROCs for updates/inserts/deletes - while still using the same validation rules, and working with the same code snippets above.

    How to Use SPROCs for Insert/Update/Delete Scenarios

    We can modify the data access layer we've been building to use SPROCs to handle updates, instead of dynamic SQL, in one of two ways:

    1) By using the LINQ to SQL designer to graphically configure SPROCs to execute in response to Insert/Update/Delete operations on our data model classes.

    or:

    2) By adding a NorthwindDataContext partial class in our project, and then by implementing the appropriate Insert/Update/Delete partial methods provided on it (for example: InsertOrder, UpdateOrder, DeleteOrder) that will be called when we insert/update/delete data model objects.  These partial methods will be passed the data model instances we want to update, and we can then execute whatever SPROC or SQL code we want to save it within the database. 

    When we use approach #1 (the LINQ to SQL designer) to graphically configure SPROCs to call, it is under the covers generating the same code (in a partial class it creates) that you'd write when using approach #2.  In general I'd recommend using the LINQ to SQL designer to configure the SPROCs for the 90% case - and then in more advanced scenarios go in and custom tweak the SPROC invocation code it generates if you need to. 

    Step 3: Doing Order Inserts with a SPROC

    We'll begin switching our data model to use SPROCs by starting with the Order object. 

    We'll first go to the Visual Studio "Server Explorer" window, expand into the "Stored Procedures" node of our database, and then right-click and choose "Add New Stored Procedure":

    We'll then create a new SPROC that we'll call "InsertOrder" that inserts a new order record into our Orders table:

    Notice above how the SPROC defines the "OrderID" parameter as an output param.  This is because the OrderID column in the database is an identity column that is set to auto-increment each time a new record is added.  The caller of the SPROC will pass in NULL as a value when calling it - and the SPROC then passes back the newly created OrderID value as the output value (by calling the SCOPE_IDENTITY() function at the end of the SPROC).

    After creating the SPROC we'll then open up the LINQ to SQL ORM designer for our data access layer.  Like I discussed in my last blog post in this series (Part 6: Retrieving Data Using Stored Procedures), we can drag/drop SPROCs from the server-explorer onto the method pane of our DataContext designer.  We'll want to-do this with our newly created InsertOrder SPROC:

    Our last step will be to tell our data access layer to use the InsertOrder SPROC when inserting new Order objects into the database.  We can do that by selecting the "Order" class in the LINQ to SQL ORM designer, and then by going to the property grid and clicking the "..." button to override how Insert operations happen for it:

    Clicking the "..." button will bring up a dialog that allows us to customize how insert operations happen:

    Notice above how the default mode ("Use Runtime") is to have LINQ to SQL calculate and execute dynamic SQL to handle the insert operations.  We can change that by selecting the "Customize" radio button and then pick our InsertOrder SPROC from the list of available SPROCs:

    The LINQ to SQL designer will populate a parameter list for the SPROC we picked, and enable us to map properties on our Order class to parameters of our InsertOrder SPROC.  By default it is smart and tries to "best match" them based on name.  You can go in and override them if you want.

    Once we click "ok" on the dialog, we are done.  Now whenever a new Order is added to our DataContext and the SubmitChanges() method is invoked, our InsertOrder SPROC will be used instead of executing dynamic SQL. 

    Important: Even though we are now using a SPROC for persistence, the custom Order "OnValidate()" partial method we created earlier (in step 1 of this blog post) to encapsulate Order validation rules still executes before any changes are saved or the SPROC is invoked.  This means we have a clean way to encapsulate business and validation rules in our data models, and can re-use them regardless of whether dynamic SQL or SPROCs are used.

    Step 4: Doing Customer Updates with a SPROC

    Now let's modify our Customer object to handle updates using a SPROC.

    We'll start by creating a new "UpdateCustomer" SPROC like below:

     

    Notice above how in addition to passing in the @CustomerID parameter, we are also passing in a @Original_CustomerID parameter.  The CustomerID column in the Customers table is not an auto-increment identity column, and it can be modified as part of an update of the Customer object.  Consequently we need to be able to provide the SPROC with both the original CustomerID and the new CustomerID in order to update the record.  We'll look at how we map this using the LINQ to SQL designer shortly.

    You'll notice above how I'm also passing in a @Version parameter (which is a timestamp) to the SPROC.  This is a new column I've added to the Northwind Customers table to help handle optimistic concurrency.  I will cover optimistic concurrency in much more depth in a later blog post in this LINQ to SQL series - but the short summary is that LINQ to SQL fully supports optimistic concurrency, and enables you to use either a version timestamp or to supply both original/new values to your SPROCs to detect if changes have been made by another user since you last refreshed your data objects.  For this sample I'm using a timestamp since it makes the code much cleaner.

    Once we've created our SPROC, we can drag/drop it onto the LINQ to SQL designer to add it as a method on our DataContext.  We can then select the Customer class in the ORM designer and click the "..." button to override the Customer object's Update behavior in the property grid:

    We'll select the "Customize" radio button and pick our UpdateCustomer SPROC to use:

    When mapping our Customer object's properties to the SPROC parameters, you'll notice that we'll want to be deliberate about whether we supply the "current" property value on the data object, or the original value that was in the database when the object was first retrieved.  For example, we'll want to make sure we map the "current" value of the Customer.CustomerID property for the @CustomerID SPROC parameter, and that we map the original value for the @original_customerID SPROC parameter.

    Once we click "ok" on the dialog, we are done.  Now whenever a new Customer is updated and the SubmitChanges() method is invoked, our UpdateCustomer SPROC will be used instead of executing dynamic SQL. 

    Important: Even though we are now using a SPROC for persistence, the Customer "OnPhoneChanging()" partial method we created earlier (in step 1 of this blog post) to encapsulate Phone Number validation rules still executes before any changes are saved or the SPROC is invoked.  We have a clean way to encapsulate business and validation rules in our data models, and can re-use them regardless of whether dynamic SQL or SPROCs are used.

    Step 5: Using our Data Access Layer Again (this time with SPROCs)

    Once we've updated our data layer to use SPROCs instead of dynamic SQL for persistence, we can re-run the exact same code we wrote in Step 2 earlier against our data model classes:

    Now the updates for the Customer object, and the insert for the Order object, are executing via SPROCs instead of dynamic SQL.  The validation logic we defined still executes just like before, though, and the data access code we write to use the data model classes is exactly the same.

    Some Advanced Notes When Using SPROCs

    A few quick notes that you might find useful for more advanced SPROC scenarios with LINQ to SQL:

    Usage of SPROC Output Params:

    In the Insert scenario (Step 3) above I showed how we could return back the new OrderID value (which is an auto-increment identity column in the Orders table) using an output parameter of the SPROC.  You aren't limited to only returning back identity column values when using SPROCs with LINQ to SQL - in fact you can update and return back output values for any parameter of your SPROC.  You can use this approach both for Insert and Update scenarios.  LINQ to SQL will then take the return value and use it to update the property value of your data model object without you having to-do any second queries against the database to refresh/populate them. 

    What Happens if the SPROC Throws an Error?

    If a SPROC raises an error when doing an Insert/Update/Delete operation, LINQ to SQL will automatically cancel and rollback the transaction of all changes associated with the current SubmitChanges() call on the DataContext.  This ensures that your data is always kept in a clean, consistent state. 

    Can you write code instead of using the ORM designer to call SPROCs?

    As I mentioned earlier in this post, you can use either the LINQ to SQL ORM designer to map your insert/update/delete operations to SPROCs, or you can add partial methods on your DataContext class and programmatically invoke them yourself.  Here is an example of the explicit code you could write in a partial class for the NorthwindDataContext to override the UpdateCustomer behavior to call a SPROC:

    The code above was actually what was generated by the LINQ to SQL ORM designer when we used the designer to map the SPROC and then associate the update behavior of the Customer object with it.  You can use it as a starting point and then add any additional logic you want to it to make it more advanced (for example: use the return value of the SPROC to raise custom exceptions for error conditions, optimistic concurrency, etc).

    Summary

    LINQ to SQL is a very flexible ORM.  It enables you to write clean object-oriented code to retrieve, update and insert data.

    Best of all - it enables you to cleanly design data model classes independent of how they are persisted and loaded from a database.  You can use the built-in ORM engine to efficiently retrieve and update data in the database using dynamic SQL.  Or alternatively you can configure your data layer to use SPROCs.  The nice thing is that your code consuming the data layer, and all of the business logic validation rules you annotate it with, can be the same regardless of which persistence approach you use.

    In future blog posts in this series I'll cover some remaining LINQ to SQL concepts including: Single Table Inheritance, Deferred/Eager Loading, Optimistic Concurrency, and handling Multi-Tier scenarios.  I'm on vacation next week, and so will hopefully have some free time to get a few of them written then. 

    Hope this helps,

    Scott

  • The asp:ListView control (Part 1 - Building a Product Listing Page with Clean CSS UI)

    One of the new controls in ASP.NET 3.5 that I think will be very popular is the <asp:ListView> control.  The ListView control supports the data editing, insertion, deleting, paging and sorting semantics of higher-level controls like the GridView.  But - unlike the GridView - it provides you with complete control over the html markup generated. 

    The ListView control, when combined with the new Web Designer and rich CSS support in VS 2008, enables you to build much cleaner HTML UI.  Over the next few weeks I'll be putting together several blog posts that show off how you can use it.

    Building a Products Catalog Page

    For today's blog post we are going to start simple and just build a basic product catalog listing page like below:

    This products.aspx page will take a Catalog index in the URL, and use LINQ to SQL to retrieve and display product information.  We will also enable paging navigation at the bottom of the product listing (and do all of the paging operations in the database - so that only 6 products at a time are retrieved from the database). 

    The HTML markup output from the server will be 100% CSS based (no tables or inline styles). 

    Step 1: Defining out Site Layout with Nested Master Pages

    Before we start working on our product page, we'll first want to define the overall UI and layout structure for our site.

    If you are "design challenged" like me, one approach you might want to take with a new site is to get started by using one of the free HTML site templates that you can download from these two sites: http://www.opensourcetemplates.org/ or http://www.oswd.org/.  The templates on these sites are pure HTML (meaning you can use them with any server-side programming technology), and are built using clean CSS and XHTML markup.  For this blog post I decided to go with the "TerraFirma" template here.

    After I downloaded the template, the first thing I did was to create a root "Site.Master" Master Page that defined the overall layout structure for the site.  I then created a few nested master pages to define different column style layouts ("SingleColumn.master" and "TwoColumn.master").  VS 2008 now has great support for creating and using nested master pages that makes doing this easy.  You can read about how to define and use them in my earlier VS 2008 Nested Master Page Support blog post.

    Once we have created our master pages layouts, we can then create a new product catalog page for the site that is based on the single-column nested master page (click below for a full screen picture):

    Notice above how we can edit the page using the new VS 2008 Split View mode feature.  Above I'm using the "Vertical Split View" option so that I can see both the source and design view on a wide-screen monitor.  You can learn how to enable this in my earlier Enabling Vertical Split View in VS 2008 blog post.

    Step 2: Defining our CSS Rules using Mock HTML UI

    When it comes to defining our product UI for the page, there are a couple of different approaches we can use.  One would be to start by writing code to generate some dynamic data UI, and then work to make it pretty.  Another approach we could take would be to start by mocking up the HTML UI first, and then once we are happy with it write the code to make it dynamic.  For this blog post I'm going to take this second approach.

    To start let's just add a standard <ul><li> list of product content into the page:

    As you can see above, this <ul> list looks pretty unattractive, and obviously not like what we want our product listing page to look like.  To make it more attractive, we'll use some of the new CSS editing features I covered in my earlier VS 2008 Web Designer and CSS Support blog post.

    Specifically we'll want to open the new "Manage Styles" tool window in VS 2008 (you can open this by selecting the Format->CSS Styles->Managed Styles menu item):

    The manage styles window provides an easy way for us to see all CSS rules currently in our CSS stylesheet.  It also enables us to quickly lookup CSS selector values, refactor css rules across stylesheets, and create new rules. 

    We can create a new CSS rule for our product listing by selecting the "New Style..." link in the "Manage Styles" window.  This will bring up a dialog that enables us to choose where we want to define the CSS rule, and configure what settings we want for it.  For this sample we'll name the CSS selector ".productslist li" and select the "Define in existing style sheet" option to add it to the external stylesheet we already have for our application:

    We can then hit "ok", and return back to source mode to assign the CSS rule on our <ul> list (note how VS 2008 now provides CSS intellisense in source view):

    Currently our CSS rule doesn't have settings assigned to it, so our <ul> list will still look the same as it did before.  We can change that by assigning some CSS settings.

    There are a couple of ways we could set these CSS settings: 1) open up the CSS stylesheet and set them in source mode, 2) use the manage styles dialog we saw before to set them, or 3) use the new CSS Properties Window to edit the CSS rules in real-time within the designer.  We can bring up the CSS Properties Windows via the View->CSS Properties menu:

    When you select an element either in source-view or design-view, the CSS Properties Windows will list all of the CSS rules that apply to it.  The "Applied Rules" list at the top of the CSS Properties window indicates the precedence order of cascading rules.  The CSS properties list below it then shows all of the setting values assigned to that element. 

    The "target rule" drop down in the style application toolbar (circled in red above) indicates which CSS selector a change in the CSS Properties window will be assigned to.  In the example above our .productlist li rule is the CSS selector we currently have selected - which means as we set values in the CSS Properties window they will be persisted under that rule name in our external CSS stylesheet.  No style settings will be persisted inline the HTML page

    Let's now make some changes to our "productlist li" CSS rule.  First we'll change the layout display mode to be "inline":

    We'll then want to float each <li> to the left:

    And lastly we'll set the bottom and left margin of each <li> element to be 15px to space out the products nicely:

    Notice how when we are done no inline styles have been saved in our HTML page:

    Instead they've all been cleanly saved under our "productlist li" CSS selector in the external CSS stylesheet:

    Now all that remains is for us to replace the static HTML with some dynamic data coming from a database.

    Step 3: Defining our LINQ to SQL Data Model

    We'll use LINQ to SQL to retrieve our product data from the database.  LINQ to SQL is a great new ORM (object relational mapper) implementation built into .NET 3.5.  You can learn more about it from my on-going LINQ to SQL blog series (more posts in it coming soon):

    We'll use the Northwind sample database for our product data, and define our data model classes in the LINQ to SQL ORM designer like so:

    Once we have our LINQ to SQL data model defined, we are ready to use the <asp:listview> control and bind the data to it.

    Step 4: Convert our HTML Mock UI to use the <asp:ListView> control

    The <asp:listview> control is a template-driven control.  The control itself outputs no "built-in" UI, nor any actual HTML markup.  Instead, you can define whatever markup *you* want displayed using the below templates:

    • LayoutTemplate
    • ItemTemplate
    • AlternatingItemTemplate
    • SelectedItemTemplate
    • EditItemTemplate
    • InsertItemTemplate
    • EmptyItemTemplate
    • EmptyDataTemplate
    • ItemSeparatorTemplate
    • GroupTemplate
    • GroupSeparatorTemplate

    The first two templates in the list above - LayoutTemplate and ItemTemplate - are the most common ones you'll end up using.  The <LayoutTemplate> template allows you to define the outer container/wrapper of your data UI.  The <ItemTemplate> template then allows you to define what each item in the list should look like. 

    Within the <LayoutTemplate> you then define an "ItemContainer" control that indicates where you want the <asp:ListView> control to dynamically add the <ItemTemplate> items into the output markup.

    To see how this works in action, we could take our mock products HTML UI:

    And replace it with a <asp:listview> that can dynamically generate the exact same markup output like so:

    Notice above how I am using a <asp:placeholder> control in the <LayoutTemplate> to indicate where I want to add in my items in the list.  I could use other controls instead as the itemContainer if I wanted to - but by using an <asp:placeholder> control as the itemContainer I will prevent any id values or extra markup being generated.

    Notice above how I've also defined an <EmptyDataTemplate>.  This will display instead of the <LayoutTemplate> if I assign an empty sequence of data to the ListView.  This will avoid us inadvertently displaying an empty <ul></ul> element in the event that there are no products in the catalog specified.   

    Once we've defined our template above, we can write some code in our code-behind file to retrieve our product data using LINQ to SQL, and bind our ListView with it:

    VB:

    C#:

    And now when we run the page and supply a valid categoryid as a querystring argument we'll see our products dynamically pulled from the database:

    If we try a category that doesn't contain products, we'll get our empty template message:

    If you do a "view source" on the products page in the browser, you'll see that the markup generated from our ListView control is the same as what our static HTML was:

    There are no ID elements or inline styles generated.  We had complete control over every HTML element and attribute generated.

    Step 5: Using a <asp:LinqDataSource> control instead of writing code

    In our previous step above we wrote procedural LINQ to SQL code to databind our <asp:ListView>.  This obviously works, and provides a great deal of control over the logic executed.

    Another option you can alternatively use is a declarative ASP.NET datasource control.  All of the ASP.NET 2.0 datasource controls (SqlDataSource, ObjectDataSource, AccessDataSource, XmlDataSource, SiteMapDataSource, etc) work with the ListView.  You can also use the new <asp:LinqDataSource> control with it.  For more information on the LinqDataSource, check out my previous LINQ to SQL Part 5: Binding UI using the ASP:LinqDataSource Control blog post.

    To use the <asp:LinqDataSource> in the above sample, we'll first delete the previous code we wrote in the code-behind file, and then click on the <asp:ListView> control in the designer and select the "Choose Data Source->New DataSource" option.  We'll pick the "LINQ DataSource" option in the data source dialog, and then bind to the Northwind data model we created earlier. 

    We can then choose to bind the ListView against the "Products" entity collection in our Northwind data model:

    We can then hit the "Where" button to configure a LINQ filter based on the "category" value in the querystring (we could alternatively bind the value from a form value, cookie, session value, another control, etc):

    When we press the "ok" button the ListView's DataSourceID will be set to a new <asp:LinqDataSource> in the page:

    And now without us having to have any code in the application we have a product listing with custom HTML UI databinding against our LINQ to SQL data model.

    Step 6: Enabling Server Side Paging using the <asp:DataPager> control

    Our last step with this sample will be to enable paging support over the products data.  Specifically, we only want to display 6 products at a time on the page, and provide a nice page number UI to allow users to navigate forward and backwards over our product sequence.

    One of the other new controls in ASP.NET 3.5 is the <asp:DataPager> control - which makes data paging scenarios with the ListView control pretty easy.  You can drop it anywhere you want on a page, and set its "PagedControlID" property to point at the ListView, and its "PageSize" property to indicate how many items in the ListView you want displayed at a time:

    The <asp:DataPager> will then output navigation UI for your ListView:

    And then if you click the "2" link in the paging UI above it will show you the remaining 5 products in the category:

    The <asp:LinqDataSource> automatically uses LINQ to SQL's built-in support for server-side data paging to ensure that only 6 products (because the PageSize is 6) are ever retrieved from the database at a time.  This means that your application and database will scale even if you have thousands of products in a specific category.

    Disclaimer: The <asp:DataPager> in Beta2, though, does have some limitations in that it can't by default be driven off of a querystring value - which makes it not very SEO friendly.  I'll cover how to fix this and support a querystring index in a future blog post.

    Summary

    Hopefully the above walkthrough provides a good first look overview of how to use the new <asp:ListView> control.  You will find that this control provides you with complete control over the markup output sent down to a client - while still providing rich data paging, editing, deleting and insertion semantics.  I'll cover many more of these scenarios (along with the ListView's cool grouping functionality) in future blog posts.

    Click here to download a copy of the above sample in order to try it out on your own machine.

    Hope this helps - and have a great weekend!

    Scott

  • Great New ASP.NET 2.0 Data Tutorials Published

    Over the last year Scott Mitchell has written 75 awesome data access tutorials covering ASP.NET 2.0 and VS 2005.  You can read all of them for free on the www.asp.net site (VB and C# versions are provided for each tutorial).

    Earlier this week we published the last 9 articles in the series:

    Scott Mitchell has more details on them on this blog post (make sure to thank him for writing all of these!).

    Hope this helps,

    Scott

    P.S. All of the tutorials are available in both HTML as well as in a PDF format that you can download and print/take offline.

  • Using LINQ to XML (and how to build a custom RSS Feed Reader with it)

    One of the big programming model improvements being made in .NET 3.5 is the work being done to make querying data a first class programming concept.  We call this overall querying programming model "LINQ", which stands for .NET Language Integrated Query.

    LINQ supports a rich extensibility model that facilitates the creation of efficient domain-specific providers for data sources.  .NET 3.5 ships with built-in libraries that enable LINQ support against Objects, XML, and Databases.

    What is LINQ to XML?

    LINQ to XML is a built-in LINQ data provider that is implemented within the "System.Xml.Linq" namespace in .NET 3.5.

    LINQ to XML provides a clean programming model that enables you to read, construct and write XML data.  You can use LINQ to XML to perform LINQ queries over XML that you retrieve from the file-system, from a remote HTTP URL or web-service, or from any in-memory XML content. 

    LINQ to XML provides much richer (and easier) querying and data shaping support than the low-level XmlReader/XmlWriter API in .NET today.  It also ends up being much more efficient (and uses much less memory) than the DOM API that XmlDocument provides. 

    Using LINQ to XML to query a local XML File

    To get a sense of how LINQ to XML works, we can create a simple XML file on our local file-system like below that uses a custom schema we've defined to store RSS feeds:

    I could then use the new XDocument class within the System.Xml.Linq namespace to open and query the XML document above.  Specifically, I want to filter the <Feed> elements in the XML file and return a sequence of the non-disabled RSS feeds (where a disabled feed is a <Feed> element with a "status" attribute whose value is "disabled").  I could accomplish this by writing the code below:

    VB:

    C#:

    Notice in the code-snippets above how I'm loading the XML file using the XDocument.Load(path) static method - which returns back an XDocument object.  Because I'm running this code within ASP.NET, I'm using the Server.MapPath(path) helper method to resolve the correct path for my XML file relative to the page I'm running the code on.

    Once I have an XDocument object for my XML file I can then write a LINQ query expression to retrieve the XML data I'm looking for.  In the code above I'm querying over each of the <Feed> elements within the XML file.  This is driven by this opening clause in the LINQ query expression:

    from feed in feedXML.Decedents("Feed")

    I'm then applying a filter that only returns back those "Feed" elements that either don't have a "status" attribute, or whose "status" attribute value is not set to "disabled":

    Where (feed.Attribute("status") Is Nothing) OrElse (feed.Attribute("status").Value <> "disabled")

    I am then using the select clause in our LINQ expression to indicate what data I want returned.  If I simply wrote "select feed", LINQ to XML would return back a sequence of XElement objects that represents each of the XML element nodes that match my filter.  In the code samples above, though, I am using the shaping/projection features of LINQ to instead define a new anonymous type on the fly, and I am defining two properties on it - Name and Feed - that I want populated using the <Name> and <Url> sub-elements under each <Feed> element:

    Select Name = feed.Element("Name").Value, Url = feed.Element("Url").Value

    As you can see above (and below), I can then work against this returned sequence of data just like I would any collection or array in .NET.  VS 2008 provides full intellisense and compilation checking support over this anonymous type sequence:

    I can also data-bind the results against any UI control in ASP.NET, Windows Forms, or WPF.  For example, assuming I had a dropdownlist control defined in my page like so:

    I could use the below LINQ to XML code to databind the results to it:

    This will then produce a nice drop-downlist in our HTML page like so:

    Hmm - What is this "anonymous type" thing?

    In my code above I've taken advantage of a new language feature in VB and C# called "anonymous types".  Anonymous types enable developers to concisely define inline CLR types within code, without having to explictly define a formal class declaration of the type.  You can learn more about them in my previous New "Orcas" Language Feature: Anonymous Types blog post.

    While anonymous types can be super useful when you want to locally iterate and work with data, we'll often want/need to define a standard class when passing the results of our LINQ query between multiple classes, across class library assemblies, and over web-services. 

    To enable this, I could define a non-anonymous class called "FeedDefinition" to represent our Feed data like so:

    Note above how I'm using the new "Automatic Properties" feature of C# to define the properties (and avoid having to define a field for them).

    I could then write the below method to return back a generics based List<FeedDefinition> collection containing FeedDefinition objects:

    Note above how the only change I've made to the LINQ to XML query we were using before is to change the "select" clause from "select new" (with no type-name) to "select new FeedDefinition".  With this change I'm now returning a sequence of FeedDefinition objects that I can pass from class to class, assembly to assembly, and across web-services.

    Using LINQ to XML to Retrieve a Remote RSS XML Feed

    The XDocument.Load(path) static method supports the ability open both XML files from the file-system, as well as remote XML feeds returned from an HTTP URL.  This enables you to use it to access remote RSS feeds, REST APIs, as well as any other XML feed published on the web.

    For an example of this in action, let's take a look at the XML of my blog's RSS feed (http://weblogs.asp.net/scottgu/rss.aspx):

    I could write the LINQ to XML code below to retrieve the above blog post data from my RSS feed, and work with the individual feed items as .NET objects:

    Note above how I am converting the "Published" field in the RSS field - which is a string in the XML - to a .NET DateTime object.  Notice also how LINQ to XML includes a built-in XNamespace type that provides a type-safe way to declare and work with XML Namespaces (which I need to-do to retrieve the <slash:comments> element).

    I could then take advantage of the composition features of LINQ to perform a further sub-query on the result, so that I filter over only those RSS posts that were published within the last 7 days using the code below:

    As you can see above, you can feed the results of one LINQ query expression to be the input of another LINQ expression.   This enables you to write very clean, highly composable, code.

    Using LINQ Sub-Queries within a LINQ to XML Query Expression

    If you look at the raw XML of my RSS feed, you'll notice that the "tag" comments for each post are stored as repeated <category> elements directly below each <item> element:

    When designing the object model for a "BlogEntry" class, I might want to represent these <category> values as a sub-collection of strings.  For example, using a "Tags" property that is a generic list of type string:

    You might be wondering - how do we take a flat collection of <category> elements under <item> and transform them into a nested sub-collection of strings?  The nice thing about LINQ is that it makes this type of scenario easy by allowing us to use nested LINQ query expressions like so:

    This "shaping" power of LINQ, and its ability to take flat data structures and make them hierarchical (and take hierarchical data structures and make them flat) is super powerful.  You can use this feature with any type of data source - regardless of whether it is XML, SQL, or plain old objects/arrays/collections.

    Putting it all Together with a Simple RSS Feed Reader

    The code snippets I've walked through above demonstrate how you can easily write LINQ to XML code to retrieve a list of RSS feeds from a local XML file, and how to remotely query an RSS feed to retrieve an individual feed's details and individual item post contents.  I could obviously then take the resulting feed contents and data-bind it to a ASP.NET GridView or ListView control to provide a nice view of the blog feed:

    I've built a simple sample application that puts all of these snippets together to deliver a simple RSS Reader with LINQ to XML and the new <asp:ListView> control.  You can download it here.  Included in the download is both a VB and C# version of the application.

    Summary

    LINQ to XML provides a really powerful way to efficiently query, filter, and shape/transform XML data.  You can use it both against local XML content, as well as remote XML feeds.  You can use it to easily transform XML data into .NET objects and collections that you can further manipulate and transfer across your application.

    LINQ to XML uses the same core LINQ query syntax and concepts that LINQ to SQL, LINQ to Objects, LINQ to SharePoint, LINQ to Amazon, LINQ to NHibernate, etc. use when querying data. You can learn more about the LINQ query syntax and the supporting language features being added to VB and C# to support it from these previous blog posts of mine:

    You might also find these blog posts of mine useful to learn more about LINQ to SQL:

    In a future blog post I'll return to LINQ to XML and demonstrate how it can be used not just to query XML, but also to really cleanly generate XML output from a .NET data structure. 

    Hope this helps,

    Scott

  • LINQ to SQL Debug Visualizer

    Probably the biggest programming model improvement being made in .NET 3.5 is the work being done to make querying data a first class programming concept.  We call this overall querying programming model "LINQ", which stands for .NET Language Integrated Query.  Developers can use LINQ with any data source, and built-in libraries are included with .NET 3.5 that enable LINQ support against Objects, XML, and Databases.

    Earlier this summer I started writing a multi-part blog series that discusses the built-in LINQ to SQL provider in .NET 3.5.  LINQ to SQL is an ORM (object relational mapping) implementation that allows you to model a relational database using .NET classes.  You can then query the database using LINQ, as well as update/insert/delete data from it.  LINQ to SQL fully supports transactions, views, and stored procedures.  It also provides an easy way to integrate data validation and business logic rules into your data model.

    You can learn more about LINQ to SQL by reading my posts below (more will be coming soon):

    Using the LINQ to SQL Debug Visualizer

    One of the nice development features that LINQ to SQL supports is the ability to use a "debug visualizer" to hover over a LINQ expression while in the VS 2008 debugger and inspect the raw SQL that the ORM will ultimately execute at runtime when evaluating the LINQ query expression.

    For example, assume we write the below LINQ query expression code against a set of data model classes:

    We could then use the VS 2008 debugger to hover over the "products" variable after the query expression has been assigned:

    And if we click the small magnifying glass in the expression above, we can launch the LINQ to SQL debug visualizer to inspect the raw SQL that the ORM will execute based on that LINQ query:

    If you click the "Execute" button, you can even test out the SQL query and see the raw returned results that will be returned from the database:

    This obviously makes it super easy to see precisely what SQL query logic LINQ to SQL ORM is doing for you. 

    You can learn even more about how all this works by reading the Part 3: Querying our Database segment in my LINQ to SQL series above.

    How to Install the LINQ to SQL Debug Visualizer

    The LINQ to SQL Debug Visualizer isn't built-in to VS 2008 - instead it is an add-in that you need to download to use.  You can download a copy of it here.

    The download contains both a binary .dll assembly version of the visualizer (within the \bin\debug directory below), as well as all of the source code for the visualizer:

    To install the LINQ to SQL debug visualizer, follow the below steps:

    1) Shutdown all running versions of Visual Studio 2008

    2) Copy the SqlServerQueryVisualizer.dll assembly from the \bin\debug\ directory in the .zip download above into your local \Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers\ directory:

    3) Start up Visual Studio 2008 again.  Now when you use the debugger with LINQ to SQL you should be able to hover over LINQ query expressions and inspect their raw SQL (no extra registration is required).

    Hope this helps,

    Scott

  • LINQ to SQL (Part 5 - Binding UI using the ASP:LinqDataSource Control)

    Over the last few weeks I've been writing a series of blog posts that cover LINQ to SQL.  LINQ to SQL is a built-in O/RM (object relational mapper) that ships in the .NET Framework 3.5 release, and which enables you to easily model relational databases using .NET classes.  You can use LINQ expressions to query the database with them, as well as update/insert/delete data.

    Below are the first four parts of my LINQ to SQL series:

    In these previous LINQ to SQL blog posts I focused on how you can programmatically use LINQ to SQL to easily query and update data within a database.

    In today's blog post I'll cover the new <asp:LinqDataSource> control that is shipping as part of ASP.NET in the upcoming .NET 3.5 release.  This control is a new datasource control for ASP.NET (like the ObjectDataSource and SQLDataSource controls that shipped with ASP.NET 2.0) which makes declaratively binding ASP.NET UI controls to LINQ to SQL data models super easy.

    Sample Application We'll be Building

    The simple data editing web application I'll walkthrough building in this tutorial is a basic data entry/manipulation front-end for products within a database:

    The application will support the following end-user features:

    1. Allow users to filter the products by category
    2. Allow users to sort the product listing by clicking on a column header (Name, Price, Units In Stock, etc)
    3. Allow users to skip/page over multiple product listings (10 products per page)
    4. Allow users to edit and update any of the product details in-line on the page
    5. Allow users to delete products from the list

    The web application will be implemented with a clean object-oriented data model built using the LINQ to SQL ORM.

    All of the business rules and business validation logic will be implemented in our data model tier - and not within the UI tier or in any of the UI pages.  This will ensure that: 1) a consistent set of business rules are used everywhere within the application, 2) we write less code and don't repeat ourselves, and 3) we can easily modify/adapt our business rules at a later date and not have to update them in dozens of different places across our application.

    We will also take advantage of the built-in paging/sorting support within LINQ to SQL to ensure that features like the product listing paging/sorting are performed not in the middle-tier, but rather in the database (meaning only 10 products are retrieved from the database at any given time - we are not retrieving thousands of rows and doing the sorting/paging within the web-server). 

    What is the <asp:LinqDataSource> control and how does it help?

    The <asp:LinqDataSource> control is an ASP.NET control that implements the DataSourceControl pattern introduced with ASP.NET 2.0.  It is similar to the ObjectDataSource and SqlDataSource controls in that it can be used to declaratively bind other ASP.NET controls on a page to a datasource.  Where it differs is that instead of binding directly to a database (like the SqlDataSource) or to a generic class (like the ObjectDataSource), the <asp:linqdatasource> is designed to bind against a LINQ enabled data model.

    One of the benefits of using the <asp:linqdatasource> control is that it leverages the flexibility that LINQ based ORMs provide.  You don't need to define custom query/insert/update/delete methods for the datasource to call - instead you can point the <asp:linqdatasource> control at your data model, identify what entity table you want it to work against, and then bind any ASP.NET UI control against the <asp:linqdatasource> and have them work with it.

    For example, to get a basic product listing UI on my page that works against Product entities within a LINQ to SQL data model, I could simply declare a <asp:linqdatasource> on my page that points to my LINQ to SQL datacontext class, and identify the entities (for example: Products) in the LINQ to SQL data model I want to bind against.  I could then point a GridView at it (by settings its DataSourceID property) to get a grid-like view of the Product content:

    Without having to-do anything else, I can run the page and have a listing of my Product data with built-in support for paging and sorting over the data.  I can add a edit/delete button on the Grid and automatically have update support as well.  I don't need to add any methods, map any parameters, or write any code for the <asp:LinqDataSource> to handle both these querying and updating scenarios - it can work against the LINQ to SQL data model we point it against and do these operations automatically.  When updates are made, the LINQ to SQL ORM will automatically ensure that all business rules and validation logic we've added (as partial methods) to the LINQ to SQL data model pass before persisting anything to the database.

    Important: The beauty of LINQ and LINQ to SQL is that it obviously isn't tied to being used only in UI scenarios - or with particular UI binding controls like the LinqDataSource.  As you've seen in my previous posts in this series, writing code using the LINQ to SQL ORM is extremely clean.  You can always write custom UI code to directly work against your LINQ to SQL data model if you prefer, or when you find a UI scenario that isn't particularly suited to using the <asp:linqdatasource>. 

    The below sections walkthrough using LINQ to SQL and the <asp:LinqDataSource> control to build the web application scenario I defined above.

    Step 1: Define our Data Model

    We'll begin working on the application by first defining the data model we'll use to represent our database. 

    I discussed how to create a LINQ to SQL data model using VS 2008's LINQ to SQL designer in Part 2 of this series.  Below is a screenshot of the data model classes I can quickly create using the LINQ to SQL designer to model the "Northwind" sample database:

    We'll revisit our data model in Step 5 of this tutorial below when we add some business validation rules to it.  But to begin with we'll just use the above data model as-is to build our UI.

    Step 2: Creating a Basic Product Listing

    We'll start our UI by creating an ASP.NET page with a <asp:gridview> control on it and use some CSS to style it:

    We could write code to programmatically bind our data model to the GridView (like I did in Part 3 of this series), or alternatively I could use the new <asp:linqdatasource> control to bind the GridView to our data model. 

    VS 2008 includes build-in designer support to make it easy to connect up our GridView (or any other ASP.NET server control) to LINQ data.  To bind our grid above to the data model we created earlier, we can switch into design-view, select the GridView, and then select the "New Data Source..." option within the "Choose Data Source:" drop-down:

    This will bring up a dialog box that lists the available datasource options to create.  Select the new "LINQ" option in the dialog box and name the resulting <asp:linqdatasource> control you want to create:

    The <asp:linqdatasource> designer will then display the available LINQ to SQL DataContext classes that your application can use (including those in class libraries that you are referencing):

    We'll want to select the data model we created with the LINQ to SQL designer earlier.  We'll then want to select the table within our data model that we want to be the primary entity for the <asp:linqdatasource> to bind against.  For this scenario we'll want to select the "Products" entity class we built.  We'll also want to select the "Advanced" button and enable updates and deletes for the datasource:

    When we click the "Finish" button above, VS 2008 will declare a <asp:linqdatasource> within our .aspx page, and update the <asp:gridview> to point to it (via its DataSourceID property).  It will also automatically provide column declarations in the Grid based on the schema of the Product entity we choose to bind against:

    We can then pull up the "smart task" context UI of the GridView and indicate that we want to enable paging, sorting, editing and deleting on it:

    We can then press F5 to run our application, and have a product listing page with full paging and sorting support (note the paging indexes at the bottom of the grid below):

    We can also select the "edit" or "delete" button on each row to update the data:

    If we flip into source view on the page, we'll see that the markup of the page contains the content below.  The <asp:linqdatasource> control points at the LINQ to SQL DataContext we created earlier, as well as the entity table we want to bind against.  The GridView then points at the <asp:linqdatasource> control (via its DataSourceID) and indicates which columns should be included in the grid, what their header text should be, as well as what sort expression to use when the column header is selected. 

    Now that we have the basics of our web UI working against our LINQ to SQL data-model, we can go ahead and further customize the UI and behavior.

    Step 3: Cleaning up our Columns

    Our GridView above has a lot of columns defined within it, and two of the column values (the SupplierID and the CategoryID) are currently foreign-key numbers -- which certainly isn't the ideal way to represent them to an end-user. 

    Removing Unnecessary Columns 

    We can start cleaning up our UI by deleting a few of the columns we don't need.  I can do this in source mode (simply nuke the <asp:boundfield> declarations) or in designer mode (just click on the column in the designer and choose the "Remove" task).  For example, we could remove the "QuantityPerUnit" column below and re-run our application to get this slightly cleaner UI:

    If you have used the <asp:ObjectDataSource> control before and explicitly passed update parameters to update methods (the default when using DataSet based TableAdapters) one of the things you know can be painful is that you have to change the method signatures of your TableAdapter's update methods when the parameters based by your UI are modified.  For example: if we deleted a column in our grid (like above), we'd end up having to modify our TableAdapter to support update methods without that parameter.

    One of the really nice things about the <asp:LinqDataSource> control is that you do not need to-do these types of changes.  Simply delete (or add) a column from your UI and re-run the application - no other changes are required.  This makes changing web UI built using the <asp:LinqDataSource> much easier, and enables much faster scenarios iterations within an application.

    Cleaning up the SupplierID and CategoryID Columns

    Currently we are displaying the foreign-key integer values in our GridView for the Supplier and Category of each Product: 

    While accurate from a data model perspective, it isn't very end-user friendly.  What I really want to-do is to display the CategoryName and SupplierName instead, and provide a drop-downlist while in Edit mode to enable end-users to easily associate the SupplierID and CategoryID values.

    I can change the GridView to display the Supplier Name and Category Name instead of the ID's by replacing the default <asp:BoundField> in our GridView with an <asp:TemplateField>.  Within this TemplateField I can add any content I want to customize the look of the column. 

    In the source code below I'm going to take advantage of the fact that each Product class in the LINQ to SQL data model we created has a Supplier and Category property on it. What this means is that I can easily databind their Supplier.CompanyName and Category.CategoryName sub-properties within our Grid:

     

    And now when I run the application I get the human readable Category and Supplier name values instead:

    To get drop-down list UI for the Supplier and Category columns while in Edit-Mode in the Grid, I will first add two additional <asp:LinqDataSource> controls to my page.  I will configure these to bind against the Categories and Suppliers within the LINQ to SQL data model we created earlier:

    I can then go back to the <asp:TemplateField> columns we added to our GridView earlier and customize their edit appearance (by specifying an EditItemTemplate).  We'll customize each column to have a dropdownlist control when in edit mode, where the available values in the dropdownlists are pulled from the categories and suppliers datasource controls above, and where we two-way databind the selected value to the Product's SupplierID and CategoryID foreign keys:

    And now when end-users click edit in the GridView, they are presented a drop-down list of all valid Supplier's to associate the product with:

    And when they hit save the Product is updated appropriately (the GridView will use the DropDownList's currently selected value to bind the SupplierID).

    Step 4: Filtering our Product Listing

    Rather than show all products within the database, we can update our UI to include a dropdownlist that allows the user to filter the products by a particular category. 

    Because we already added a <asp:LinqDataSource> control to the page earlier that references our Categories within our LINQ to SQL data model, all I need to-do to create a drop-downlist control at the top of the page that binds against this.  For example:

    When I run the page I'll now get a filter dropdownlist of all categories at the top of the page:

    My last step is to configure the GridView to only show those Products in the category the end-user selects from the dropdownlist.  The easiest way to-do this is by selecting the "Configure DataSource" option in the GridView smart task:

    This will bring me back to the <asp:LinqDataSource> control's design-time UI that we used at the very beginning of this tutorial.  I can select the "Where" button within this to add a binding filter to the datasource control.  I can add any number of filter expressions, and declaratively pull the values to filter by from a variety of places (for example: from the querystring, from form-values, from other controls on the page, etc):

    Above I'm going to choose to filter by the Products by their CategoryID value, and then retrieve this CategoryID from the DropDownList control we just created on our page:

    When we hit finish, the <asp:linqdatasource> control in our page will have been updated to reflect this filter clause like so:

    And when we now run the page the end-user will now be able to select from the available Categories in the filter drop-downlist and page, sort, edit and delete just the products in that category:

    The <asp:LinqDataSource> control will automatically apply the appropriate LINQ filter expression when working against our LINQ to SQL data model classes to ensure that only the required data is retrieved from the database (for example: in the Grid above only the 3 rows of Product data from the second page of Confection products will be retrieved from the database).

    You can optionally handle the Selecting event on the <asp:LinqDataSource> if you want to write a custom LINQ expression in code to completely customize the query instead.

    Step 5: Adding Business Validation Rules

    As I discussed in Part 4 of this LINQ to SQL series, when we define LINQ to SQL data models we will automatically have a default set of schema based validation constraints added to our data model classes.  This means that if I try and enter a null value for a required column, try and assign a string to an integer, or assign a foreign-key value to a row that doesn't exist, our LINQ to SQL data model will raise an error and ensure that our database integrity is maintained.

    Basic schema validation is only a first step, though, and is rarely enough for most real-world applications.  Typically we'll want/need to add additional business rules and application-level validation to our data model classes.  Thankfully LINQ to SQL makes adding these types of business validation rules easy (for details on the various validation approaches available, please read Part 4 of my LINQ to SQL series).

    Example Business Validation Rule Scenario

    For example, let's consider a basic business logic rule we might want to enforce.  Specifically, we want to ensure that a user of our application can't discontinue a product while we still have units on backorder for it:

    If a user tries to save the above row, we'll want to prevent this change from being persisted and throw an appropriate error telling the user how to fix it.

    Adding a Data Model Validation Rule

    The wrong place to add this type of business validation rule is in the UI layer of our application.  Adding it in the UI layer of our application will mean that the rule will be specific to only that one place, and will not be automatically enforced when we add another page to our application that also updates Products.  Distributing business rules/logic in our UI layer will also make life extremely painful as our application grows in size - since changes/updates to our business will necessitate making code changes all over the place.

    The right place to specify this type of business logic validation is instead in our LINQ to SQL data model classes that we defined earlier.  As I discussed in Part 4 of this series, all classes generated by the LINQ to SQL designer are defined as "partial" classes - which means that we can easily add additional methods/events/properties to them.  The LINQ to SQL data model classes automatically call validation methods that we can implement to enforce custom validation logic within them.

    For example, I could add a partial Product class to my project that implements the OnValidate() partial method that LINQ to SQL calls prior to persisting a Product entity.  Within this OnValidate() method I could add the following business rule to enforce that products can't have a Reorder Level if the product is discontinued:

    Once I add the above class into my LINQ to SQL project, the above business rule will be enforced anytime anyone uses my data model to try and modify the database.  This is true for both updating existing Products, as well as adding new Products into the database.

    Because the <asp:LinqDataSource> that we defined in our pages above works against our LINQ to SQL data model classes, all of its update/insert/delete logic will now have to pass the above validation check prior to the change being persisted.  We do not need to-do anything to our UI tier in order for this validation to occur - it will automatically be applied anywhere and everywhere our LINQ to SQL data model is used.

    Adding Nice Error Handling in our UI Tier

    By default if a user now uses our GridView UI to enter a non-valid UnitsOnOrder/Discontinued combination, our LINQ to SQL data model classes will raise an exception.  The <asp:LinqDataSource> will in turn catch this error and provides an event that users can use to handle it.  If no one handles the event then the GridView (or other) control bound to the <asp:LinqDataSource> will catch the error and provide an event for users to handle it.  If no one handles the error there then it will be passed up to the Page to handle, and if not there to the global Application_Error() event handler in the Global.asax file.  Developers can choose any place along this path to insert appropriate error handling logic to provide the right end-user experience.

    For the application we defined above, probably the best place to handle any update errors is by handling the RowUpdated event on our GridView.  This event will get fired every time an update is attempted on our datasource, and we can access the exception error details if the update event fails.  We can add the below code to check if an error occurs, and if so display an appropriate error message to the end-user:

    Notice above how we have not added any validation specific logic into our UI.  Instead, I am retrieving the validation error message string we raised in our business logic and am using it to display an appropriate message to the end-user (I am then displaying a more generic error message in the event of other failures). 

    Notice how I'm also indicating above that I want the GridView to stay in Edit mode when an error occurs - that way the user can avoid losing their changes, and can modify the values they entered and click "update" again to try and save them.  We can then add a <asp:literal> control with the "ErrorMessage" ID anywhere we want on our page to control where where we want the error message to be displayed:

    And now when we try and update the Product with an invalid value combination we'll see an error message indicating how to fix it:

    The nice thing about using this approach is that I can now add or change my data model's business rules and not have to modify any of my UI tier's code to have them pick up and honor the changes.  The validation rules, and corresponding error messages, can be written and centralized in one place in my data model and automatically applied everywhere.

    Summary

    The <asp:LinqDataSource> control provides an easy way to bind any ASP.NET UI control to a LINQ to SQL data model.  It enables UI controls to both retrieve data from a LINQ to SQL data model, as well as cleanly apply updates/inserts/deletes to it. 

    In our application above we used the LINQ to SQL ORM designer to create a clean, object oriented data model.  We then added three ASP.NET UI controls to our page (a GridView, a DropDownList, and a ErrorMessage Literal), and added three <asp:LinqDataSource> controls to bind Product, Category, and Supplier data from it:

    We then wrote 5 lines of business validation logic in our data model, and 11 lines of UI error handling logic. 

    The end result is a simple web application with custom UI that allows users to dynamically filter product data by category, efficiently sort and page over the product results, inline-edit the product data to save updates (providing our business rules pass), and delete products from the system (also providing our business rules allow it).

    In future posts in this series I'll cover more LINQ to SQL scenarios including optimistic concurrency, lazy and eager loading, table mapping inheritance, and custom SQL/SPROC usage.

    Next week I also plan to start a new series of blog posts that cover the new <asp:ListView> control - which is a new control that will ship with the ASP.NET release in .NET 3.5.  It provides total control over the markup generated for data scenarios (no tables, no spans, no inline styles...), while also delivering built-in support for paging, sorting, editing, and insertion scenarios.  For example, we could optionally use it to replace the default Grid layout look of our application above with a completely custom look and feel.  Best of all, I could replace it within the above page in my application and not have to change my Data Model, the <asp:linqdatasource> declaration, or my code-behind UI error handling logic at all.

    Hope this helps,

    Scott

  • LINQ to SQL (Part 4 - Updating our Database)

    Over the last few weeks I've been writing a series of blog posts that cover LINQ to SQL.  LINQ to SQL is a built-in O/RM (object relational mapper) that ships in the .NET Framework 3.5 release, and which enables you to easily model relational databases using .NET classes.  You can use LINQ expressions to query the database with them, as well as update/insert/delete data.

    Below are the first three parts of my LINQ to SQL series:

    In today's blog post I'll cover how we we can use the data model we created earlier, and use it to update, insert, and delete data.  I'll also show how we can cleanly integrate business rules and custom validation logic with our data model.

    Northwind Database Modeled using LINQ to SQL

    In Part 2 of this series I walked through how to create a LINQ to SQL class model using the LINQ to SQL designer that is built-into VS 2008.  Below is a class model created for the Northwind sample database and which I'll be using in this blog post:

     

    When we designed our data model using the LINQ to SQL data designer above we defined five data model classes: Product, Category, Customer, Order and OrderDetail.  The properties of each class map to the columns of a corresponding table in the database.  Each instance of a class entity represents a row within the database table.

    When we defined our data model, the LINQ to SQL designer also created a custom DataContext class that provides the main conduit by which we'll query our database and apply updates/changes.  In the example data model we defined above this class was named "NorthwindDataContext".  The NorthwindDataContext class has properties that represent each Table we modeled within the database (specifically: Products, Categories, Customers, Orders, OrderDetails).

    As I covered in Part 3 of this blog series, we can easily use LINQ syntax expressions to query and retrieve data from our database using this NorthwindDataContext class.  LINQ to SQL will then automatically translate these LINQ query expressions to the appropriate SQL code to execute at runtime.

    For example, I could write the below LINQ expression to retrieve a single Product object by searching on the Product name:

    I could then write the LINQ query expression below to retrieve all products from the database that haven't yet had an order placed for them, and which also cost more than $100:

    Note above how I am using the "OrderDetails" association for each product as part of the query to only retrieve those products that have not had any orders placed for them.

    Change Tracking and DataContext.SubmitChanges()

    When we perform queries and retrieve objects like the product instances above, LINQ to SQL will by default keep track of any changes or updates we later make to these objects.  We can make any number of queries and changes we want using a LINQ to SQL DataContext, and these changes will all be tracked together. 

    Note: LINQ to SQL change tracking happens on the consuming caller side - and not in the database.  This means that you are not consuming any database resources when using it, nor do you need to change/install anything in the database to enable it.

    After making the changes we want to the objects we've retrieved from LINQ to SQL, we can then optionally call the "SubmitChanges()" method on our DataContext to apply the changes back to the database.  This will cause LINQ to SQL to dynamically calculate and execute the appropriate SQL code to update the database.

    For example, I could write the below code to update the price and # of units in stock of the "Chai" product in the database:

    When I call northwind.SubmitChanges() above, LINQ to SQL will dynamically construct and execute a SQL "UPDATE" statement that will update the two product property values we modified above.

    I could then write the below code to loop over unpopular, expensive products and set the "ReorderLevel" property of them to zero:

    When I call northwind.SubmitChanges() above, LINQ to SQL will calculate and execute an appropriate set of UPDATE statements to modify the products who had their ReorderLevel property changed.

    Note that if a Product's property values weren't changed by the property assignments above, then the object would not be considered changed and LINQ to SQL would therefore not execute an update for that product back to the database.  For example - if the "Chai" product's unitprice was already $2 and the number of units in stock was 4, then calling SubmitChanges() would not cause any database update statements to execute.  Likewise, only those products in the second example whose ReorderLevel was not already 0 would be updated when the SubmitChanges() method was called.

    Insert and Delete Examples

    In addition to updating existing rows in the database, LINQ to SQL obviously also enables you to insert and delete data.  You can accomplish this by adding/removing data objects from the DataContext's table collections, and by then calling the SubmitChanges() method.  LINQ to SQL will keep track of these additions/removals, and automatically execute the appropriate SQL INSERT or DELETE statements when SubmitChanges() is invoked.

    Inserting a New Product

    I can add a new product to my database by creating a new "Product" class instance, setting its properties, and then by adding it to my DataContext's "Products" collection:

    When we call "SubmitChanges()" above a new row will be created in our products table.

    Deleting Products

    Just as I can express that I want to add a new Product to the database by adding a Product object into the DataContext's Products collection, I can likewise express that I want to delete a product from a database by removing it from the DataContext's Products collection:

    Note above how I'm retrieving a sequence of discontinued products that no one has ever ordered using a LINQ query, and then passing it to the RemoveAll() method on my DataContext's "Products" collection.  When we call "SubmitChanges()" above all of these Product rows will be deleted from our products table.

    Updates across Relationships

    What makes O/R mappers like LINQ to SQL extremely flexible is that they enable us to easily model cross-table relationships across our data model.  For example, I can model each Product to be in a Category, each Order to contain OrderDetails for line-items, associate each OrderDetail line-item with a Product, and have each Customer contain an associated set of Orders.  I covered how to construct and model these relationships in Part 2 of this blog series.

    LINQ to SQL enables me to take advantage of these relationships for both querying and updating my data. For example, I could write the below code to create a new Product and associate it with an existing "Beverages" category in my database like so:

    Note above how I'm adding the Product object into the Category's Products collection.  This will indicate that there is a relationship between the two objects, and cause LINQ to SQL to automatically maintain the foreign-key/primary key relationship between the two when I call "SubmitChanges()".

    For another example of how LINQ to SQL can help manage cross-table relationships for us and help clean up our code, let's look at an example below where I'm creating a new Order for an existing customer.  After setting the required ship date and freight costs for the order, I then create two order line-item objects that point to the products the customer is ordering.  I then associate the order with the customer, and update the database with all of the changes.

    As you can see, the programming model for performing all of this work is extremely clean and object oriented. 

    Transactions

    A transaction is a service provided by a database (or other resource manager) to guarantee that a series of individual actions occur atomically - meaning either they all succeed or they all don't, and if they don't then they are all automatically undone before anything else is allowed to happen.

    When you call SubmitChanges() on your DataContext, the updates will always be wrapped in a Transaction.  This means that your database will never be in an inconsistent state if you perform multiple changes - either all of the changes you've made on your DataContext are saved, or none of them are.

    If no transaction is already in scope, the LINQ to SQL DataContext object will automatically start a database transaction to guard updates when you call SubmitChanges(). Alternatively, LINQ to SQL also enables you to explicitly define and use your own TransactionScope object (a feature introduced in .NET 2.0).  This makes it easier to integrate LINQ to SQL code with existing data access code you already have.  It also means that you can enlist non-database resources into the transaction - for example: you could send off a MSMQ message, update the file-system (using the new transactional file-system support), etc - and scope all of these work items in the same transaction that you use to update your database with LINQ to SQL.

    Validation and Business Logic

    One of the important things developers need to think about when working with data is how to incorporate validation and business rule logic.  Thankfully LINQ to SQL supports a variety of ways for developers to cleanly integrate this with their data models. 

    LINQ to SQL enables you to add this validation logic once - and then have it be honored regardless of where/how the data model you've created is used.  This avoids you having to repeat logic in multiple places, and leads to a much more maintainable and clean data model. 

    Schema Validation Support

    When you define your data model classes using the LINQ to SQL designer in VS 2008, they will by default be annotated with some validation rules inferred from the schema of the tables in the database.

    The datatypes of the properties in the data model classes will match the datatypes of the database schema.  This means you will get compile errors if you attempt to assign a boolean to a decimal value, or if you attempt to implicitly convert numeric types incorrectly.

    If a column in the database is marked as being nullable, then the corresponding property in the data model class created by the LINQ to SQL designer will be a nullable type.  Columns not marked as nullable will automatically raise exceptions if you attempt to persist an instance with a null value.  LINQ to SQL will likewise ensure that identity/unique column values in the database are correctly honored.

    You can obviously use the LINQ to SQL designer to override these default schema driven validation settings if you want - but by default you get them automatically and don't have to take any additional steps to enable them.  LINQ to SQL also automatically handles escaping SQL values for you - so you don't need to worry about SQL injection attacks when using it.

    Custom Property Validation Support

    Schema driven datatype validation is useful as a first step, but usually isn't enough for real-world scenarios. 

    Consider for example a scenario with our Northwind database where we have a "Phone" property on the "Customer" class which is defined in the database as an nvarchar.  Developers using LINQ to SQL could write code like below to update it using a valid telephone number: 

    The challenge that we will run into with our application, however, is that the below code is also legal from a pure SQL schema perspective (because it is still a string even though it is not a valid phone number):

    To prevent bogus phone numbers from being added into our database, we can add a custom property validation rule to our Customer data model class.  Adding a rule to validate phone numbers using this feature is really easy.  All we need to-do is to add a new partial class to our project that defines the method below:

    The code above takes advantage of two characteristics of LINQ to SQL:

    1) All classes created by the LINQ to SQL designer are declared as "partial" classes - which means that developers can easily add additional methods, properties, and events to them (and have them live in separate files).  This makes it very easy to augment the data model classes and DataContext classes created by the LINQ to SQL designer with validation rules and additional custom helper methods that you define.  No configuration or code wire-up is required.

    2) LINQ to SQL exposes a number of custom extensibility points in its data model and DataContext classes that you can use to add validation logic before and after things take place.  Many of these extensibility points utilize a new language feature called "partial methods" that is being introduced with VB and C# in VS 2008 Beta2.  Wes Dyer from the C# team has a good explanation of how partial methods works in this blog post here.

    In my validation example above, I'm using the OnPhoneChanging partial method that is executed anytime someone programmatically sets the "Phone" property on a Customer object.  I can use this method to validate the input however I want (in this case I'm using a regular expression).  If everything passes successfully, I just return from the method and LINQ to SQL will assume that the value is valid.  If there are any issues with the value, I can raise an exception within the validation method - which will prevent the assignment from taking place.

    Custom Entity Object Validation Support

    Property level validation as used in the scenario above is very useful for validating individual properties on a data model class.  Sometimes, though, you want/need to validate multiple property values on an object against each other. 

    Consider for example a scenario with an Order object where you set both the "OrderDate" and the "RequiredDate" properties:

    The above code is legal from a pure SQL database perspective - even though it makes absolutely no sense for the required delivery date of the new order to be entered as yesterday. 

    The good news is that LINQ to SQL in Beta2 makes it easy for us to add custom entity level validation rules to guard against mistakes like this from happening.  We can add a partial class for our "Order" entity and implement the OnValidate() partial method that will be invoked prior to the entity's values being persisted into the database.  Within this validation method we can then access and validate all of the data model class properties:

    Within this validation method I can check any of the entity's property values (and even obtain read-only access to its associated objects), and raise an exception as needed if the values are incorrect.  Any exceptions raised from the OnValidate() method will abort any changes from being persisted in the database, and rollback all other changes in the transaction.

    Custom Entity Insert/Update/Delete Method Validation

    There are times when you want to add validation logic that is specific to insert, update or delete scenarios.  LINQ to SQL in Beta2 enables this by allowing you to add a partial class to extend your DataContext class and then implement partial methods to customize the Insert, Update and Delete logic for your data model entities.  These methods will be called automatically when you invoke SubmitChanges() on your DataContext.

    You can add appropriate validation logic within these methods - and if it passes then tell LINQ to SQL to continue with persisting the relevant changes to the database (by calling the DataContext's "ExecuteDynamicXYZ" method):

    What is nice about adding the above methods is that the appropriate ones are automatically invoked regardless of the scenario logic that caused the data objects to be created/updated/deleted.  For example, consider a simple scenario where we create a new Order and associate it with an existing Customer:

    When we call northwind.SubmitChanges() above, LINQ to SQL will determine that it needs to persist a new Order object, and our "InsertOrder" partial method will automatically be invoked. 

    Advanced: Looking at the Entire Change List for the Transaction

    There are times when adding validation logic can't be done purely by looking at individual insert/update/delete operations - and instead you want to be able to look at the entire change list of operations that are occurring for a transaction. 

    Starting with Beta2 of .NET 3.5, LINQ to SQL now enables you to get access to this change list by calling the public DataContext.GetChangeList() method.  This will return back a ChangeList object that exposes collections of each addition, removal and modification that has been made. 

    One approach you can optionally employ for advanced scenarios is to sub-class the DataContext class and override its SubmitChange() method.  You can then retrieve the ChangeList() for the update operation and perform any custom validation you want prior to executing it:

     

    The above scenario is a somewhat advanced one - but it is nice to know that you always have the ability to drop-down and take advantage of it if needed.

    Handling Simultaneous Changes with Optimistic Concurrency

    One of the things that developers need to think about in multi-user database systems is how to handle simultaneous updates of the same data in the database.  For example, assume two users retrieve a product object within an application, and one of the users changes the ReorderLevel to 0 while the other changes it to 1.  If both users then attempt to save the product back to the database, the developer needs to decide how to handle the change conflicts. 

    One approach is to just "let the last writer win" - which means that the first user's submitted value will be lost without the end-users realizing it.  This is usually considered a poor (and incorrect) application experience. 

    Another approach which LINQ to SQL supports is to use an optimistic concurrency model - where LINQ to SQL will automatically detect if the original values in the database have been updated by someone else prior to the new values being persisted.  LINQ to SQL can then provide a conflict list of changed values to the developer and enable them to either reconcile the differences or provide the end-user of the application with UI to indicate what they want to-do. 

    I'll cover how to use optimistic concurrency with LINQ to SQL in a future blog post.

    Using SPROCs or Custom SQL Logic for Insert/Update/Delete Scenarios

    One of the questions that developers (and especially DBAs) who are used to writing SPROCs with custom SQL usually ask when seeing LINQ to SQL for the first time is - "but how can I have complete control of the underlying SQL that is executed?" 

    The good news is that LINQ to SQL has a pretty flexible model that enables developers to override the dynamic SQL that is automatically executed by LINQ to SQL, and instead call custom insert, update, delete SPROCs that they (or a DBA) define themselves. 

    What is really nice is that you can start off by defining your data model and have LINQ to SQL automatically handle the insert, update, delete SQL logic for you.  You can then at a later point customize the data model to use your own custom SPROCs or SQL for updates - without having to change any of the application logic that is using your data model, nor would you have to change any of the validation or business rules logic supporting it (all of this stays the same).  This provides a lot of flexibility in how you build your application.

    I'll cover how to customize your data models to use SPROCs or custom SQL in a future blog post.

    Summary

    Hopefully the above post provides a good summary of how you can easily use LINQ to SQL to update your database, and cleanly integrate validation and business logic with your data models.  I think you'll find that LINQ to SQL can dramatically improve your productivity when working with data, and enable you to write extremely clean object-oriented data access code.

    In upcoming blog posts in this series I'll cover the new <asp:linqdatasource> control coming in .NET 3.5, and talk about how you can easily build data UI in ASP.NET that takes advantage of LINQ to SQL data models. I'll also cover some more specific LINQ to SQL programming concepts including optimistic concurrency, lazy and eager loading, table mapping inheritance, custom SQL/SPROC usage, and more.

    Hope this helps,

    Scott

  • LINQ to SQL (Part 3 - Querying our Database)

    Last month I started a blog post series covering LINQ to SQL.  LINQ to SQL is a built-in O/RM (object relational mapping) framework that ships in the .NET Framework 3.5 release, and which enables you to easily model relational databases using .NET classes.  You can then use LINQ expressions to query the database with them, as well as update/insert/delete data from it.

    Below are the first two parts of my LINQ to SQL series:

    In today's blog post I'll be going into more detail on how to use the data model we created in the Part 2 post, and show how to use it to query data within an ASP.NET project.

    Northwind Database Modeled using LINQ to SQL

    In Part 2 of this series I walked through how to create a LINQ to SQL class model using the LINQ to SQL designer that is built-into VS 2008.  Below is the class model that we created for the Northwind sample database:

    Retrieving Products

    Once we have defined our data model classes above, we can easily query and retrieve data from our database.  LINQ to SQL enables you to do this by writing LINQ syntax queries against the NorthwindDataContext class that we created using the LINQ to SQL designer above.

    For example, to retrieve and iterate over a sequence of Product objects I could write code like below:

    In the query above I have used a "where" clause in my LINQ syntax query to only return those products within a specific category.  I am using the CategoryID of the Product to perform the filter.

    One of the nice things above LINQ to SQL is that I have a lot of flexibility in how I query my data, and I can take advantage of the associations I've setup when modeling my LINQ to SQL data classes to perform richer and more natural queries against the database.  For example, I could modify the query to filter by the product's CategoryName instead of its CategoryID by writing my LINQ query like so:

    Notice above how I'm using the "Category" property that is on each of the Product objects to filter by the CategoryName of the Category that the Product belongs to.  This property was automatically created for us by LINQ to SQL because we modeled the Category and Product classes as having a many to one relationship with each other in the database.

    For another simple example of using our data model's association relationships within queries, we could write the below LINQ query to retrieve only those products that have had 5 or more orders placed for them:

    Notice above how we are using the "OrderDetails" collection that LINQ to SQL has created for us on each Product class (because of the 1 to many relationship we modeled in the LINQ to SQL designer).

    Visualizing LINQ to SQL Queries in the Debugger

    Object relational mappers like LINQ to SQL handle automatically creating and executing the appropriate SQL code for you when you perform a query or update against their object model. 

    One of the biggest concerns/fears that developers new to ORMs have is "but what SQL code is it actually executing?"  One of the really nice things about LINQ to SQL is that it makes it super easy to see exactly what SQL code it is executing when you run your application within the debugger.

    Starting with Beta2 of Visual Studio 2008 you can use a new LINQ to SQL visualizer plug-in to easily see (and test out) any LINQ to SQL query expression.  Simply set a breakpoint and then hover over a LINQ to SQL query and click the magnify glass to pull up its expression visualizer within the debugger:

    This will then bring up a dialog that shows you the exact SQL that LINQ to SQL will use when executing the query to retrieve the Product objects:

    If you press the "Execute" button within this dialog it will allow you to evaluate the SQL directly within the debugger and see the exact data results returned from the database:

    This obviously makes it super easy to see precisely what SQL query logic LINQ to SQL is doing for you.  Note that you can optionally override the raw SQL that LINQ to SQL executes in cases where you want to change it - although in 98% of scenarios I think you'll find that the SQL code that LINQ to SQL executes is really, really good.

    Databinding LINQ to SQL Queries to ASP.NET Controls

    LINQ queries return results that implement the IEnumerable interface - which is also an interface that ASP.NET server controls support to databind object.  What this means is that you can databind the results of any LINQ, LINQ to SQL, or LINQ to XML query to any ASP.NET control.

    For example, we could declare an <asp:gridview> control in a .aspx page like so:

    I could then databind the result of the LINQ to SQL query we wrote before to the GridView like so:

    This will then generate a page that looks like below:

    Shaping our Query Results

    Right now when we are evaluating our product query, we are retrieving by default all of the column data needed to populate the Product entity classes. 

    For example, this query to retrieve products:

    Results in all of this data being returned:

     

    Often we only want to return a subset of the data about each product.  We can use the new data shaping features that LINQ and the new C# and VB compilers support to indicate that we only want a subset of the data by modifying our LINQ to SQL query like so:

    This will result in only this data subset being returned from our database (as seen via our debug visualizer):

    What is cool about LINQ to SQL is that I can take full advantage of my data model class associations when shaping my data.  This enables me to express really useful (and very efficient) data queries.  For example, the below query retrieves the ID and Name from the Product entity, the total number of orders that have been made for the Product, and then sums up the total revenue value of each of the Product's orders:

    The expression to the right of the "Revenue" property above is an example of using the "Sum" extension method provided by LINQ.  It takes a Lambda expression that returns the value of each product order item as an argument. 

    LINQ to SQL is smart and is able to convert the above LINQ expression to the below SQL when it is evaluated (as seen via our debug visualizer):

    The above SQL causes all of the NumOrders and Revenue value computations to be done inside the SQL server, and results in only the below data being retrieved from the database (making it really fast):

    We can then databind the result sequence against our GridView control to generate pretty UI:

    BTW - in case you were wondering, you do get full intellisense within VS 2008 when writing these types of LINQ shaping queries:

    In the example above I'm declaring an anonymous type that uses object initialization to shape and define the result structure.  What is really cool is that VS 2008 provides full intellisense, compilation checking, and refactoring support when working against these anonymous result sequences as well:

     

    Paging our Query Results

    One of the common needs in web scenarios is to be able to efficiently build data paging UI.  LINQ provides built-in support for two extension methods that make this both easy and efficient - the Skip() and Take() methods.

    We can use the Skip() and Take() methods below to indicate that we only want to return 10 product objects - starting at an initial product row that we specify as a parameter argument:

    Note above how I did not add the Skip() and Take() operator on the initial products query declaration - but instead added it later to the query (when binding it to my GridView datasource).  People often ask me "but doesn't this mean that the query first grabs all the data from the database and then does the paging in the middle tier (which is bad)?"  No.  The reason is that LINQ uses a deferred execution model - which means that the query doesn't actually execute until you try and iterate over the results. 

    One of the benefits of this deferred execution model is that it enables you to nicely compose queries across multiple code statements (which improves code readability).  It also enables you to compose queries out of other queries - which enables some very flexible query composition and re-use scenarios.

    Once I have the BindProduct() method defined above, I can write the code below in my page to retrieve the starting index from the querystring and cause the products to be paged and displayed in the gridview:

    This will then give us a products page, filtered to list only those products with more than 5 orders, showing dynamically computed product data, and which is pageable via a querystring argument:

    Note: When working against SQL 2005, LINQ to SQL will use the ROW_NUMBER() SQL function to perform all of the data paging logic in the database.  This ensures that only the 10 rows of data we want in the current page view are returned from the database when we execute the above code:

    This makes it efficient and easy to page over large data sequences.

    Summary

    Hopefully the above walkthrough provides a good overview of some of the cool data query opportunities that LINQ to SQL provides.  To learn more about LINQ expressions and the new language syntax supported by the C# and VB compilers with VS 2008, please read these earlier posts of mine:

    In my next post in this LINQ to SQL series I'll cover how we can cleanly add validation logic to our data model classes, and demonstrate how we can use it to encapsulate business logic that executes every time we update, insert, or delete our data.  I'll then cover more advanced lazy and eager loading query scenarios, how to use the new <asp:LINQDataSource> control to support declarative databinding of ASP.NET controls, optimistic concurrency error resolution, and more.

    Hope this helps,

    Scott

  • LINQ to SQL (Part 2 - Defining our Data Model Classes)

    In Part 1 of my LINQ to SQL blog post series I discussed "What is LINQ to SQL" and provided a basic overview of some of the data scenarios it enables.

    In my first post I provided code samples that demonstrated how to perform common data scenarios using LINQ to SQL including:

    • How to query a database
    • How to update rows in a database
    • How to insert and relate multiple rows in a database
    • How to delete rows in a database
    • How to call a stored procedure
    • How to retrieve data with server-side paging

    I performed all of these data scenarios using a LINQ to SQL class model that looked like the one below:

    In this second blog post in the series I'm going to go into more detail on how to create the above LINQ to SQL data model.

    LINQ to SQL, the LINQ to SQL Designer, and all of the features that I'm covering in this blog post series will ship as part of the .NET 3.5 and Visual Studio "Orcas" release. 

    You can follow all of the steps below by downloading either Visual Studio "Orcas" Beta 1 or Visual Web Developer Express "Orcas" Beta1.  Both can be installed and used side-by-side with VS 2005.

    Create a New LINQ to SQL Data Model

    You can add a LINQ to SQL data model to an ASP.NET, Class Library or Windows client project by using the "Add New Item" option within Visual Studio and selecting the "LINQ to SQL" item within it:

    Selecting the "LINQ to SQL" item will launch the LINQ to SQL designer, and allow you to model classes that represent a relational database.  It will also create a strongly-typed "DataContext" class that will have properties that represent each Table we modeled within the database, as well as methods for each Stored Procedure we modeled.  As I described in Part 1 of this blog post series, the DataContext class is the main conduit by which we'll query entities from the database as well as apply changes back to it.

    Below is a screen-shot of an empty LINQ to SQL ORM designer surface, and is what you'll see immediately after creating a new LINQ to SQL data model:

     

    Entity Classes

    LINQ to SQL enables you to model classes that map to/from a database.  These classes are typically referred to as "Entity Classes" and instances of them are called "Entities".  Entity classes map to tables within a database.  The properties of entity classes typically map to the table's columns.  Each instance of an entity class then represents a row within the database table.

    Entity classes defined with LINQ to SQL do not have to derive from a specific base class, which means that you can have them inherit from any object you want.  All classes created using the LINQ to SQL designer are defined as "partial classes" - which means that you can optionally drop into code and add additional properties, methods and events to them.

    Unlike the DataSet/TableAdapter feature provided in VS 2005, when using the LINQ to SQL designer you do not have to specify the SQL queries to use when creating your data model and access layer. 

    Instead, you focus on defining your entity classes, how they map to/from the database, and the relationships between them.  The LINQ to SQL OR/M implementation will then take care of generating the appropriate SQL execution logic for you at runtime when you interact and use the data entities.  You can use LINQ query syntax to expressively indicate how to query your data model in a strongly typed way.

    Creating Entity Classes From a Database

    If you already have a database schema defined, you can use it to quickly create LINQ to SQL entity classes modeled off of it.

    The easiest way to accomplish this is to open up a database in the Server Explorer within Visual Studio, select the Tables and Views you want to model in it, and drag/drop them onto the LINQ to SQL designer surface:

     

    When you add the above 2 tables (Categories and Products) and 1 view (Invoices)  from the "Northwind" database onto the LINQ to SQL designer surface, you'll automatically have the following three entity classes created for you based on the database schema:

     

    Using the data model classes defined above, I can now run all of the code samples (expect the SPROC one) described in Part 1 of this LINQ to SQL series.  I don't need to add any additional code or configuration in order to enable these query, insert, update, delete, and server-side paging scenarios. 

    Naming and Pluralization

    One of the things you'll notice when using the LINQ to SQL designer is that it automatically "pluralizes" the various table and column names when it creates entity classes based on your database schema.  For example: the "Products" table in our example above resulted in a "Product" class, and the "Categories" table resulted in a "Category" class.  This class naming helps make your models consistent with the .NET naming conventions, and I usually find having the designer fix these up for me really convenient (especially when adding lots of tables to your model).  

    If you don't like the name of a class or property that the designer generates, though, you can always override it and change it to any name you want.  You can do this either by editing the entity/property name in-line within the designer or by modifying it via the property grid:

     

    The ability to have entity/property/association names be different from your database schema ends up being very useful in a number of cases.  In particular:

    1) When your backend database table/column schema names change.  Because your entity models can have different names from the backend schema, you can decide to just update your mapping rules and not update your application or query code to use the new table/column name.

    2) When you have database schema names that aren't very "clean".  For example, rather than use "au_lname" and "au_fname" for the property names on an entity class, you can just name them to "LastName" and "FirstName" on your entity class and develop against that instead (without having to rename the column names in the database).

    Relationship Associations

    When you drag objects from the server explorer onto the LINQ to SQL designer, Visual Studio will inspect the primary key/foreign key relationships of the objects, and based on them automatically create default "relationship associations" between the different entity classes it creates.  For example, when I added both the Products and Categories tables from Northwind onto my LINQ to SQL designer you can see that a one to many relationship between the two is inferred (this is denoted by the arrow in the designer):

    The above association will cause cause the Product entity class to have a "Category" property that developers can use to access the Category entity for a given Product.  It will also cause the Category class to have a "Products" collection that enables developers to retrieve all products within that Category.

    If you don't like how the designer has modeled or named an association, you can always override it.  Just click on the association arrow within the designer and access its properties via the property grid to rename, delete or modify it.

    Delay/Lazy Loading

    LINQ to SQL enables developers to specify whether the properties on entities should be prefetched or delay/lazy-loaded on first access.  You can customize the default pre-fetch/delay-load rules for entity properties by selecting any entity property or association in the designer, and then within the property-grid set the "Delay Loaded" property to true or false.

    For a simple example of when I'd want to-do this, consider the "Category" entity class we modeled above.  The categories table inside "Northwind" has a "Picture" column which stores a (potentially large) binary image of each category, and I only want to retrieve the binary image from the database when I'm actually using it (and not when doing a simply query just to list the category names in a list).

    I could configure the Picture property to be delay loaded by selecting it within the LINQ to SQL designer and by settings its Delay Loaded value in the property grid:

    Note: In addition to configuring the default pre-fetch/delay load semantics on entities, you can also override them via code when you perform LINQ queries on the entity class (I'll show how to-do this in the next blog post in this series).

    Using Stored Procedures

    LINQ to SQL allows you to optionally model stored procedures as methods on your DataContext class.  For example, assume we've defined the simple SPROC below to retrieve product information based on a categoryID:

    I can use the server explorer within Visual Studio to drag/drop the SPROC onto the LINQ to SQL designer surface in order to add a strongly-typed method that will invoke the SPROC.  If I drop the SPROC on top of the "Product" entity in the designer, the LINQ to SQL designer will declare the SPROC to return an IEnumerable<Product> result:

    I can then use either LINQ Query Syntax (which will generate an adhoc SQL query) or alternatively invoke the SPROC method added above to retrieve product entities from the database:

    Using SPROCs to Update/Delete/Insert Data

    By default LINQ to SQL will automatically create the appropriate SQL expressions for you when you insert/update/delete entities.  For example, if you wrote the LINQ to SQL code below to update some values on a "Product" entity instance:

    By default LINQ to SQL would create and execute the appropriate "UPDATE" statement for you when you submitted the changes (I'll cover this more in a later blog post on updates).

    You can also optionally define and use custom INSERT, UPDATE, DELETE sprocs instead.  To configure these, just click on an entity class in the LINQ to SQL designer and within its property-grid click the "..." button on the Delete/Insert/Update values, and pick a particular SPROC you've defined instead:

    What is nice about changing the above setting is that it is done purely at the mapping layer of LINQ to SQL - which means the update code I showed earlier continues to work with no modifications required.  This avoids developers using a LINQ to SQL data model from having to change code even if they later decide to put in a custom SPROC optimization later.

    Summary

    LINQ to SQL provides a nice, clean way to model the data layer of your application.  Once you've defined your data model you can easily and efficiently perform queries, inserts, updates and deletes against it. 

    Using the built-in LINQ to SQL designer within Visual Studio and Visual Web Developer Express you can create and manage your data models for LINQ to SQL extremely fast.  The LINQ to SQL designer also provides a lot of flexibility that enables you to customize the default behavior and override/extend the system to meet your specific needs.

    In upcoming posts I'll be using the data model we created above to drill into querying, inserts, updates and deletes further.  In the update, insert and delete posts I'll also discuss how to add custom business/data validation logic to the entities we designed above to perform additional validation logic.

    Mike Taulty also has a number of great LINQ to SQL videos that I recommend checking out here.  These provide a great way to learn by watching someone walkthrough using LINQ to SQL in action.

    Hope this helps,

    Scott

  • Using LINQ to SQL (Part 1)

    Over the last few months I wrote a series of blog posts that covered some of the new language features that are coming with the Visual Studio and .NET Framework "Orcas" release.  Here are pointers to the posts in my series:

    The above language features help make querying data a first class programming concept.  We call this overall querying programming model "LINQ" - which stands for .NET Language Integrated Query.

    Developers can use LINQ with any data source.  They can express efficient query behavior in their programming language of choice, optionally transform/shape data query results into whatever format they want, and then easily manipulate the results.  LINQ-enabled languages can provide full type-safety and compile-time checking of query expressions, and development tools can provide full intellisense, debugging, and rich refactoring support when writing LINQ code.

    LINQ supports a very rich extensibility model that facilitates the creation of very efficient domain-specific operators for data sources.  The "Orcas" version of the .NET Framework ships with built-in libraries that enable LINQ support against Objects, XML, and Databases.

    What Is LINQ to SQL?

    LINQ to SQL is an O/RM (object relational mapping) implementation that ships in the .NET Framework "Orcas" release, and which allows you to model a relational database using .NET classes.  You can then query the database using LINQ, as well as update/insert/delete data from it.

    LINQ to SQL fully supports transactions, views, and stored procedures.  It also provides an easy way to integrate data validation and business logic rules into your data model.

    Modeling Databases Using LINQ to SQL:

    Visual Studio "Orcas" ships with a LINQ to SQL designer that provides an easy way to model and visualize a database as a LINQ to SQL object model.  My next blog post will cover in more depth how to use this designer (you can also watch this video I made in January to see me build a LINQ to SQL model from scratch using it). 

    Using the LINQ to SQL designer I can easily create a representation of the sample "Northwind" database like below:

    My LINQ to SQL design-surface above defines four entity classes: Product, Category, Order and OrderDetail.  The properties of each class map to the columns of a corresponding table in the database.  Each instance of a class entity represents a row within the database table.

    The arrows between the four entity classes above represent associations/relationships between the different entities.  These are typically modeled using primary-key/foreign-key relationships in the database.  The direction of the arrows on the design-surface indicate whether the association is a one-to-one or one-to-many relationship.  Strongly-typed properties will be added to the entity classes based on this.  For example, the Category class above has a one-to-many relationship with the Product class.  This means it will have a "Categories" property which is a collection of Product objects within that category.  The Product class then has a "Category" property that points to a Category class instance that represents the Category to which the Product belongs.

    The right-hand method pane within the LINQ to SQL design surface above contains a list of stored procedures that interact with our database model.  In the sample above I added a single "GetProductsByCategory" SPROC.  It takes a categoryID as an input argument, and returns a sequence of Product entities as a result.  We'll look at how to call this SPROC in a code sample below.

    Understanding the DataContext Class

    When you press the "save" button within the LINQ to SQL designer surface, Visual Studio will persist out .NET classes that represent the entities and database relationships that we modeled.  For each LINQ to SQL designer file added to our solution, a custom DataContext class will also be generated.  This DataContext class is the main conduit by which we'll query entities from the database as well as apply changes.  The DataContext class created will have properties that represent each Table we modeled within the database, as well as methods for each Stored Procedure we added.

    For example, below is the NorthwindDataContext class that is persisted based on the model we designed above:

    LINQ to SQL Code Examples

    Once we've modeled our database using the LINQ to SQL designer, we can then easily write code to work against it.  Below are a few code examples that show off common data tasks:

    1) Query Products From the Database

    The code below uses LINQ query syntax to retrieve an IEnumerable sequence of Product objects.  Note how the code is querying across the Product/Category relationship to only retrieve those products in the "Beverages" category:

    C#:

    VB:

    2) Update a Product in the Database

    The code below demonstrates how to retrieve a single product from the database, update its price, and then save the changes back to the database:

    C#:

    VB:

    Note: VB in "Orcas" Beta1 doesn't support Lambdas yet.  It will, though, in Beta2 - at which point the above query can be rewritten to be more concise.

    3) Insert a New Category and Two New Products into the Database

    The code below demonstrates how to create a new category, and then create two new products and associate them with the category.  All three are then saved into the database.

    Note below how I don't need to manually manage the primary key/foreign key relationships. Instead, just by adding the Product objects into the category's "Products" collection, and then by adding the Category object into the DataContext's "Categories" collection, LINQ to SQL will know to automatically persist the appropriate PK/FK relationships for me. 

    C#

    VB:

    4) Delete Products from the Database

    The code below demonstrates how to delete all Toy products from the database:

    C#:

    VB:

    5) Call a Stored Procedure

    The code below demonstrates how to retrieve Product entities not using LINQ query syntax, but rather by calling the "GetProductsByCategory" stored procedure we added to our data model above.  Note that once I retrieve the Product results, I can update/delete them and then call db.SubmitChanges() to persist the modifications back to the database.

    C#:

    VB:

    6) Retrieve Products with Server Side Paging

    The code below demonstrates how to implement efficient server-side database paging as part of a LINQ query.  By using the Skip() and Take() operators below, we'll only return 10 rows from the database - starting with row 200.

    C#:

    VB:

    Summary

    LINQ to SQL provides a nice, clean way to model the data layer of your application.  Once you've defined your data model you can easily and efficiently perform queries, inserts, updates and deletes against it. 

    Hopefully the above introduction and code samples have helped whet your appetite to learn more.  Over the next few weeks I'll be continuing this series to explore LINQ to SQL in more detail.

    Hope this helps,

    Scott

  • Video: Using LINQ with ASP.NET in VS "Orcas" (Part 1)

    One of my goals this year is to use video more with my blog.  My theory is that video is often a better medium than text to walkthrough how something works, and can also help you avoid the tedium of reading though some of my really long blog posts... :-)

    Over the next few months I'm going to try and create a new video every other week or so on various topics.  Many of these videos are going to involve first looks at some of the new features coming with Visual Studio "Orcas", which is our new release that will ship later this year.  For today's video I decided to focus on introducing LINQ - which I think is one of the most exciting features coming with "Orcas". 

    At a high-level, LINQ makes the concept of query a first class programming concept within .NET.  Using LINQ you can easily query relational databases, XML files, as well as any plain-old .NET object.  You can also easily use your own data source abstractions with LINQ to provide rich domain models for various data providers (for a great example of this check out Fabrice's LINQ to Amazon implementation that supports LINQ queries against Amazon data exposed via web-services).  Both VB and C# include rich language integration with LINQ as part of the "Orcas" release, including full intellisense, compile-time checking, and debugging support.

    Watch or Download the Video

    This first video starts with a new project, and then demonstrates the basics of using LINQ against a SQL Database to build a simple data reporting page (including support for aggregate values computed from multiple tables, and efficient server-side paging within the database). 

    You can watch the video online here (it is 24 minutes in length).  Or you can download a .zip version of it here if you want to save and watch it locally.  Note that it might take 30-60 seconds to buffer (since it is a large video).  In the event that my server is swamped with requests, I'll update the location and post it on one of the Microsoft video servers later this week.

    For more information on LINQ (including the slide deck for a "Building ASP.NET Data Driven Application Using LINQ" talk of mine), please check out my previous post here.  For other ASP.NET 2.0 Tips, Tricks and Tutorials please check out my ASP.NET Tips and Tricks summary listing page.

    Specifics Topics Covered in this Video

    My walkthrough in this video illustrates a number of new features:

    1) A brief demonstration of some of the new WYSIWYG HTML designer capabilities (including split-view and a brief look at the new CSS manager - both of which I'll cover in more detail in the future in a separate video):

    2) How to create classes that model data using the new VS "Orcas" ORM designer for LINQ to SQL:

    3) How to use the new LINQ intellisense support within the VS "Orcas" code editor to get full intellisense and compilation support for queries:

    4) How to use LINQ to SQL to create a data report that combines Product entity data with aggregate unit and revenue values computed from OrderDetail entities associated with the Product entities.  This data report uses server side database paging to efficiently retrieve only 10 rows of data at a time (so that with a 100,000 row products table you only ever retrieve 10 rows of data from the database regardless of which page index you are on within a report):

    Future Videos

    I'll be drilling into LINQ some more with future videos (I barely scratched the surface with this one).  Additional segments will include content on:

    • Type inference and the "var" keyword (and why that is so cool)
    • Supporting Insert, Update and Deletes scenarios using LINQ to SQL
    • Using SPROCs with LINQ to SQL
    • Richer JOIN support with LINQ to SQL
    • LINQ to XML and LINQ to Objects
    • Using the new LINQDataSource controls and other ASP.NET Data Controls to easily create Web UI with LINQ

    I'll also obviously have many more ASP.NET and web-related video topics to cover including:

    • The new HTML WYSIWYG Designer and CSS support
    • Client-JavaScript Intellisense
    • JavaScript Debugging
    • ASP.NET AJAX Extender Support
    • Database Dump and Upload Integration
    • Unit Testing
    • Multi-targeting support (showing how you can use VS "Orcas" to build ASP.NET 2.0 projects - without having to upgrade your framework/server)

    Hope this helps,

    Scott

    P.S. If you have other topics and/or subjects you'd like me to drill in on with videos, please post them in the comments section of this post.

  • Recipe: Deploying a SQL Database to a Remote Hosting Environment (Part 1)

    Scenario:

    You finish building a great ASP.NET application, have everything tested and working right on your local system, are taking full advantage of the new ASP.NET 2.0 Membership, Role and Profile features, and are ready to publish it to a remote hosting environment and share it with the world. 

    Copying the .aspx files and compiled assemblies to the remote system is pretty easy (just FTP or copy them up).  The challenge that confronts a lot of developers, though, is how to setup and recreate the database contents - both schema and data - on the remote hosted site.  Unfortunately there hasn't historically been a super-easy way to accomplish this.

    The good news is that this week the SQL Server team published the release candidate of a new SQL Server Hosting Toolkit that will make it much, much easier to deploy your SQL solutions remotely to a hosted environment.  The toolkit allows you to work with SQL Express, SQL Server 2000, and SQL Server 2005 databases locally, and then easily transfer your schema and data and install them into a shared hosting remote SQL Server account.

    The below post describes how you can start using this today. 

    SQL Server Hosting Toolkit

    The SQL Server Hosting toolkit is available for free, and ships with a Database Publishing Wizard that supports two database hosting deployment scenarios:

    1) The Database Publishing Wizard enables you to point at a database you are working with on your local system, and then automatically create a .SQL script file that contains the setup logic needed to re-create an exact replica of the database on any remote system.  This .SQL script includes everything needed to create the database schema (tables, views, sprocs, triggers, full-text catalogs, roles, rules, etc - full details here), as well as populate the new database with the same table row contents as your local database (this is analogous to the MySQL dump utility).  The benefit of having this setup logic encapsulated in a single .SQL file is that most hosters already support the ability for you to upload .SQL files to their hosted environments and run these scripts via their hosting admin control panels.  Assuming you have a web hoster that supports this today, you can immediately start using the Database Publishing Wizard to easily deploy your sites without requiring anything to be installed or configured by the hoster.

    2) The Database Publishing Wizard also enables you to point at a database you are working with on your local system, and then use web-services to transfer and recreate the database in your remote hoster environment (without you having to create the .SQL file or use the hoster admin control panel to run it).  This publishing option does require that a SQL Publishing web-service be exposed in the hosting environment, and the SQL Server Hosting Toolkit includes a free implementation of this SQL Publishing web-service that we'll be working with hosters to aggressively deploy. 

    The Database Publishing Wizard enables you to use either SQL Express or SQL Server 2000/2005 locally, and then use either SQL 2000 or SQL 2005 in the remote hoster environment.  It does not require that the versions of SQL match - so you can use SQL Express 2005 locally and then upload to a SQL 2000 server in the hosting environment without having to change any of your code.  

    The Database Publishing Wizard also supports handling the built-in ASP.NET 2.0 Membership, Role Management, Profile and Health Monitoring schemas.  A lot of people have run into issues because the built-in .SQL scripts that ship by default with ASP.NET for setting up these schemas require DBO permissions at install-time for the SQL scripts -- which a lot of hosters don't support (note: the scripts do not require DBO permissions at runtime - only for install time, but this can sometimes still be a blocker in itself unless the hoster is willing to install them for you).  The Database Publishing Wizard on the other-hand does not require DBO permissions when installing the ASP.NET Membership, Roles and Profile schemas/data, and should enable you to deploy the ASPNETDB tables + sprocs just as easily as any other database using the Database Publishing Wizard. 

    First Tutorial: Deploying a SQL Express Database to a SQL Server Hosting Account (using .SQL files)

    I'll be doing a series of posts over the next few weeks showing how to use the various features within the SQL Server Hosting Toolkit.  This first tutorial in the series covers how to use it to easily generate a .SQL installation file of a local SQL Express database that you can then copy to a remote hosting account and use to re-create a SQL Server database for you to use with your hosted site.

    Step 0: Download and Install the Database Publishing Wizard

    The first step we'll need to-do is to make sure we have the Database Publishing Wizard from the SQL Hosting Toolkit installed.  Click here to download it and install it.

    The Database Publishing Wizard comes with support for both a GUI based wizard, as well as a command-line utility.  The GUI based wizard can be run either standalone or via context-menu support that it adds to the Server Explorer in both Visual Studio 2005 and Visual Web Developer Express.  For the purposes of this tutorial we'll be using this later Server Explorer integration - which makes publishing really easy.

    Step 1: Create an ASP.NET web-site that uses a local SQL Express or SQL Server database

    To help with this demo, we will use the built-in Personal Starter Kit template that ships with both VS 2005 and Visual Web Developer Express.  To create a new web project based on it, select File->New Web Site within VWD or VS and choose the "Personal Starter Kit" template in the New Web-Site dialog.  By default the personal starter kit application is configured to use SQL Express (which is free and can be downloaded here).  When run the sample looks like below:

    After creating the application, you can then run the web admin tool (choose the WebSite->ASP.NET Configuration menu item in VWD/VS) and create a new user and add them to the "admin" role for the site.  You can then login as this new admin user and try uploading new pictures and/or customizing the existing ones on the site (note that both the picture meta-data, as well as the raw image binaries are stored in a database when you do this):

     

    Once you are all done with the above steps we'll have two SQL Express databases installed within the \app_data directory for our project.  One of the SQL Express databases is named personal.mdf and contains the tables and stored procedures specific to our web-site (photo and album tables, as well as basic content management support).  The other SQL Express database is named aspnetdb.mdf and contains the database storage for the default ASP.NET 2.0 Membership, Role and Profile providers (which the application above is using for login and admin purposes).

    Step 2: Creating .SQL Installation Scripts for our Database

    Now that we've created a new application + local database, and added custom data to it (new users + their role membership, as well as new photos and albums), we want to deploy the application to a remote hosting server. 

    The first step we'll take is to create .SQL script files that will enable us to automate re-creating the exact same database schema + database content on our remote hosting account.  To-do this we'll use the Database Publishing Wizard we installed as part of the SQL Hosting Toolkit. 

    To begin, click on the "Server Explorer" tab within Visual Studio or Visual Web Developer to see the databases that the application is using:

    As you can see in the above picture, we have two SQL Express databases that we are using: ASPNETDB.MDF and Personal.MDF.  To generate .SQL installation files for each one, simply select the database in the solution explorer, then right-click and select the new "Publish to Provider" context menu item (added by the Database Publishing Wizard) setup on it:

    This will launch the Database Publishing Wizard and allow us to walkthrough scripting the installation of our database.  As I mentioned in the intro of this blog post, the Database Publishing Wizard supports two deployment options: 1) To generate .SQL install script files that you can copy to your remote hoster and run using their existing web admin control panel tools, or 2) To upload the database directly using Database Publishing Web-Services on the hoster web-site. 

    For this first tutorial, we'll be using the .SQL script file approach - so keep the default radio button selected and provide a name for the .SQL install script file you want to generate:

     

    When you click "next" you'll be given the option to customize some of preferences when creating the .SQL setup file.  Note that you can control whether to drop existing objects within the target database, whether you want to target SQL 2000 or SQL 2005 with the script, and whether you want to setup both the schema and data, or just the schema, or just the data: 

    For this tutorial just keep the defaults selected, and hit next and generate the .SQL script:

    You now have a Personal .SQL file that contains a script that you can run on any SQL server to re-create all the tables, sprocs, views, triggers, full-text catalogs, etc. for a database, as well as import and add all of the table row data that was in the database at the time the .SQL file was created. 

    The .SQL file itself is just plain text - so you can open it up with any text editor to see it and/or customize it with your own statements:

    Notice above how the .SQL file includes both the SQL DDL needed to create the Photos table (including all of its constraints and primary-key/foreign-key relationships), as well as the SQL to insert data within the table once it is created (in the case above it is even inserting binary data for the photos - since they are stored in the database). 

    Once you repeat these steps for the ASPNETDB SQL Express database as well you'll have two .SQL installation scripts that you can use to automatically re-create your SQL database on any SQL Server:

     

    Note that the .SQL files we built can be used to create two separate databases on a server, or they can both be run against the same database to create a single database that has a unified set of tables, sprocs, and data for the application.  To accomplish this, simply run both scripts against the same database, and assuming no table or sproc names conflict, you'll have a single database containing everything.  This later option is very useful when you have a hosting account that only provides 1 database instance for you to use!

    Step 3: Using our .SQL files to create our remote databases

    Now that we have our .SQL files, we can go about using them to install our database at our hoster.  Exactly how we use the .SQL files to install the database will vary depending on how the hoster gives us access to our SQL account.  Some hosters provide an HTML based file-upload tool that allows you to provide a .SQL file - which they will then execute against the SQL database you own. 

    Other hosters provide an online query tool (like below) that allows you to copy/paste SQL statements to run against your database.  If you have a hoster which provides an online query tool like this, then you can open the .SQL file with a text-editor and copy/paste the contents into the query textbox and run it.

    The quality of the SQL tools that different hosters provide varies quite a bit.  In testing the Database Publishing Wizard we found that some custom-made SQL admin tools provided by hosters had issues where they incorrectly parsed valid SQL statements (in particular GOTO statements).  This page describes one issue you might see some hosters have with GOTO statements, along with a workaround you can use.  To help improve the overall quality of SQL hosting admin tools, the SQL Server team early next year is going to be shipping the source to a free SQL HTML admin tool that hosters will be able to integrate into their experiences.  Hopefully this will help improve the standard experience with all Windows hosters.

    If your hoster has no usable HTML web admin tool for allowing you to easily manage your SQL database, then you can also just write a simple ASP.NET page that you FTP (along with your .SQL file) to your web-site and then hit to read the .SQL file on the server in as text, and then pass it as a string to ADO.NET to execute.  This will give you the same result as the query analyzer above - and fully create your database for you.

    Step 4: Updating our connection-string within web.config

    Once we've got our data uploaded within a database at our hoster, we'll want to upload our .aspx files, assemblies and content to the remote site (typically this is done over FTP). 

    The last step we'll need to take is to open up our web.config file and update the <connectionStrings> section to point at our new database location at the remote hoster.  Note that you'll need to get the exact SQL server, database name, and username/password account to use from the hoster.

    Using our personal starter kit example above, we'd change the <connectionStrings> section within its web.config file from the default connection-string (which uses two SQL Express database in the local \app_data directory):

    <connectionStrings>
       
    <add name="Personal" connectionString="Data Source=.\SQLExpress;Integrated Security=True;User Instance=True;AttachDBFilename=|DataDirectory|Personal.mdf" />   
       <
    remove name="LocalSqlServer"/>
       <
    add name="LocalSqlServer" connectionString="Data Source=.\SQLExpress;Integrated Security=True;User Instance=True;AttachDBFilename=|DataDirectory|aspnetdb.mdf" />
    </
    connectionStrings>

    To instead use a single SQL Server 2000 database (the "scottguDB" database on the "Server123" box). 

    <connectionStrings>
       
    <add name="Personal" connectionString="Data Source=Server123;Initial Catalog=scottguDB;Integrated Security=True" providerName="System.Data.SqlClient" />
       <
    remove name="LocalSqlServer"/>
       <
    add name="LocalSqlServer" connectionString="Data Source=Server123;Initial Catalog=scottguDB;Integrated Security=True" providerName="System.Data.SqlClient" />
    </
    connectionStrings>

    We were able to use a single database (instead of the two above) because we we ran both .SQL files against the single database - which merged all schema and data into a single database instance.

    Step 5: We are done

    Now we can run the application remotely in a hosted environment, and it should just work.

    Summary

    The Database Publishing Wizard that ships as part of the SQL Hosting Toolkit should make creating .SQL files for any database (SQL Express or full SQL Server) really easy.  You can use this to easily dump your local database and then use it to re-create the exact same database on a remote system.

    In future tutorials I'll also show how you can actually re-create your database remotely without even having to generate a .SQL file (instead you can publish the database directly from VS to your hoster over a web-service).  Stay tuned for details on how to-do this soon.

    Hope this helps,

    Scott

    P.S. We are planning on adding the Database Publishing Wizard into Visual Studio "Orcas" (which is the next release of VS), which means you won't need to download it separately in that timeframe.  But we wanted to make sure you didn't have to wait until then, which is why we are making it available today for Visual Studio 2005 and Visual Web Developer Express 2005.

    P.P.S. Please visit this page to find other ASP.NET Tips, Tricks and Recipes I've written on other topics in the past.

  • Building and Using a &quot;LINQ for SQL&quot; Class Library with ASP.NET 2.0

    In my previous posts on doing data access using LINQ and ASP.NET, I used the built-in SQLMetal command-line utility to automatically generate the data model classes for my LINQ data classes.  Recently I've been using the LINQ for SQL (aka DLINQ) designer to define my data models instead, and have been really impressed with how easily it enables me to build a re-usable class library that nicely encapsulates my data and business logic.

    The below walkthrough demonstrates how you can get started with it yourself.  Simply install the LINQ May CTP download on top of VS 2005, and you can then follow along all of the steps below yourself.  For the sample below I am using C#, but everything works equally well in VB as well.

     

    Step 1: Create a New LINQ Enabled Class Library

    Choose File->New Project within Visual Studio and navigate to the "LINQ Preview" node in the project-type tree-explorer.  Then select the "LINQ Library" project icon and create a new LINQ enabled class library:

    This will create a class library project whose MSBuild project file enables compilation support for LINQ.  A default "Class1.cs" file is added to the project -- I recommend just deleting it to start with an empty project.

     

    Step 2: Add a LINQ for SQL Data Model to the Project

    Right-click on the project and choose the Add->New Item context menu item.  Scroll down in the dialog and select the "DLINQ Object" icon, and give it an appropriate name (in this sample I'm naming it "Northwind" since I'm going to be modeling the Northwind database):

    This will add a Northwind.dlinq file to your project, and bring up its designer:

    You can now use the designer to map your data models and entities graphically, as well as setup associations to map relationships between them.

     

    Step 3: Quickly creating a Northwind data model

    One of the really easy ways to quickly define your data model classes is to open up the Server Explorer tab within VS 2005 and connect to your database.  You can then drill into the Tables and Views within your database, and drag/drop them from the server explorer onto the DLINQ designer surface to automatically create data models for them.  For example, if I dragged/dropped the Suppliers, Customers, Orders, Order Details, and Products tables onto the designer surface, I'd by default get a data model that looks like this:

    Note how the DLINQ designer automatically sets up default associations between the different entities based on the Primary Key/Foreign Key relationships in the database.  These will automatically cause properties to be created on the various data classes so that we can perform rich querying and/or easily traverse between them.  For example, if I had a "Customer" instance above I could simply access the "Customer.Orders" property to get a collection of all of that Customer's orders in the database.

    If you want, you can add, delete or alter these associations by simply clicking on the association links in the designer and then use the property grid to change its settings.  For example, if I wanted to modify the "Order Details" associations above to instead be named "OrderDetails", I would click on the association line in the designer and change it either via the property grid:

    Or because it supports inline editing for the name, just click on the name in the designer and rename it in place:

    Additionally, I could use the designer to easily rename the entities and/or rename/remove/add properties to them.  Once we are done defining your data models, we'll just save the file.  The designer will then automatically generate a .cs or .vb file containing the LINQ data class definitions.  This is saved in a nested file underneath the Northwind.dlinq item in the solution explorer:

    The LINQ data model classes created are defined as "partial" classes -- which means we will be able to go in later and add entity and property validation rules that enforce our business logic, as well as add any additional properties or helper methods we want to the classes.

     

    Step 4: Creating a LINQ Enabled Web-Site that References our LINQ enabled Class Library

    We'll now want to go ahead and build a LINQ-enabled ASP.NET web-site that uses our LINQ class library.  Choose File->Add->Web Site within Visual Studio to add a new project to the solution.  Choose the LINQ web-site template to create an ASP.NET web-site that is enabled with the LINQ compilers:

    Your VS solution will then look like this:

    The last two steps you'll want to take are to:

    1) Add a project reference from the web-site project to the LINQ class library.  To-do this, right-click on the web-site and select "Add Reference", select the "Projects" tab and add the reference as normal.

    2) Add a connection-string to your web.config file in the web-site project for the LINQ class library.  This will enable you to easily configure and change the connection-string that is used at runtime for the application.  Simply copy/paste the connection-string value in the LINQ class library's app.config file to the web.config file's <connectionString> section to configure this.

    Once the above two steps are done, we are ready to build ASP.NET UI pages against our LINQ class library and associated data models.

     

    Step 5: Build a simple Products Listing Page

    To give a simple taste of using LINQ, we'll build a simple Product Listing page that lists products like the image below:

    To implement this, I'll add a templated ASP.NET DataList control to the .aspx page using the markup below to define the UI for each product in our list:

    <asp:DataList ID="DataList1" RepeatColumns="2" runat="server">

        
    <ItemTemplate>
        
           
    <div class="productimage">
                
    <img src="images/productimage.gif" />
            </
    div>
        
            
    <div class="productdetails">
            
                
    <div class="ProductListHead">
                    
    <%#Eval("ProductName")%>
                
    </div>
                
                
    <span class="ProductListItem">
                    
    <strong>Price:</strong>
                    
    <%# Eval("UnitPrice", "{0:c}") %>
                
    </span>
                
            
    </div>                
        
        
    </ItemTemplate>

    </asp:DataList>

    I can then use the below code-behind class to execute a LINQ query against the class library data model we defined in our class library previously to retrieve all of the products in the database supplier by the "Exotic Liquids" supplier and sorted by the product name:

    using System;
    using 
    System.Web;
    using 
    System.Query;
    using 
    LINQClassLibrary;

    public 
    partial class HelloWorld : System.Web.UI.Page {

        
    protected void Page_Load() {

            NorthwindDataContext db 
    = new NorthwindDataContext();

            
    DataList1.DataSource from p in db.Products
                                   where p.Supplier.CompanyName == "Exotic Liquids"
     
                                   
    orderby p.ProductName
                                   select p
    ;

            
    DataList1.DataBind();
        
    }
    }

    Notice above how the LINQ query is strongly-typed, and can incorporate the Product/Supplier entity association we setup earlier (for example: note how the where statement is able to search by the product's Supplier.CompanyName property -- which is stored in the Suppliers table and is linked to the Products table via a primary key/foreign key relationship). 

    This strong typing model means I get compile-time checking of my LINQ queries today, and will get full intellisense support with the new release of Visual Studio.  No more runtime SQL syntax errors!

    And that is it.  No additional code required. 

     

    Step 6: Using Debug Visualizers to inspect what SQL is executed against the database

    One of the most common questions people wonder when using ORM data frameworks is "so what SQL code is it running under the covers?".  LINQ makes it easy to figure this out.  Just set a debugging breakpoint on a LINQ expression variable, and you can use a built-in LINQ debugging visualizer to inspect it while debugging. 

    For example, set a breakpoint on the DataList1.DataBind() method above and when it is hit hover your mouse over the DataList1.DataSource property and click the magnifying glass to launch its DLINQ query visualizer:

    This will bring up a visualizer dialog that displays the SQL statement that LINQ will execute against the database when evaluating that LINQ expression:

    If you click the "execute" button on the bottom-right you can even test out the query in the debugger and see the exact data that will be returned from it when the supplier name is "Exotic Liquids" is this:

    This makes it really easy to see the exact SQL that is executed and closely watch what is going on as you modify and refine your LINQ queries.

     

    Summary

    Hopefully the above walkthrough provides a good introduction to some of the cool things you can do with LINQ and the LINQ May CTP version of it. 

    To learn more about LINQ with ASP.NET, please checkout the post I am going to be doing in a few minutes which links to a bunch of good resources and which includes the sample I used above.

    Hope this helps,

    Scott

    Share this post: Email it! | bookmark it! | digg it! | reddit!
  • My ASP.NET 2.0 Tips, Tricks, Recipes and Gotchas "Highlights Page"

    Several people have sent me email lately asking for a suggested short-list of my best/favorite past blog posts to read (I’ve done 200 posts over the last 12 months and apparently it takes too long to read them all <g>). 

    I’ve put together a summary page of ASP.NET 2.0 Tips, Tricks, Recipes and Gotchas that you can check out here.  It currently contains links to 37 posts that I’ve done in the past that I think are interesting and worth spending sometime to read. 

    I’ve organized the list by area topic (UI, Data, Security, Visual Studio, etc).  My goal is to post at least 1-2 new/original ASP.NET Tips/Tricks/Recipes to my blog each week going forward.  I’ll also make sure to update the summary page above as I add new ones – so you might find it useful to bookmark if you want to quickly look them up.

    Hope this helps,

    Scott

    Share this post: Email it! | bookmark it! | digg it! | reddit!

This Blog

Syndication

Powered by Community Server, by Telligent Systems
'