Table of Contents

Overview

PLINQO, which stands for Professional LINQ to Objects, is a collection of CodeSmith templates that are meant to replace and extend the LINQ to SQL designers that are included with Visual Studio 2008.

Features

The templates have the following features.

Advantages Over Designer

There are several advantages to using the PLINQO templates over the Visual Studio designer. Here is a list of the main reasons:

  1. Remove the designer black box and allow for customization of the output while still retaining the ability to use the .dbml designer to make customizations inside of Visual Studio.
  2. Ability to easily generate your entire .dbml file for a database and then the ability to regenerate that .dbml file as the schema changes. The regeneration preserves any customizations you may have made such as entity, property and relationship names. With the designer, if you make a database change, you need to drop the entity and re-add it to get any new columns or data type changes, which would cause you to lose any customizations you may have made. Also, using the templates allows you to exclude unwanted tables, stored procedures and views using filter expressions and automatically strip / clean entity and property names of things like prefixes and suffixes that your database schema may be using (ie. tbl_Customer to Customer).
  3. A business rules engine that allows you to enforce things like property length rules, required field rules, regex data validation rules as well as several other built in rules including authorization rules using metadata attributes. The SubmitChanges method on the data context object will automatically run the rules against any entities in your change set. If all rules are not met, a BrokenRulesException will be thrown that contains a list of the broken rules.
  4. A manager class is generated for each entity that encapsulates all actions taken on an entity. Known common actions like retrieving entities by primary key, indexes, and foreign keys are generated. Any custom actions can be added and will be preserved during regeneration. While LINQ makes it easy to sprinkle your data access logic throughout your entire application, we still believe its poor design to do so and that is why we have included the manager classes.

Quick Start

The following steps will create a quick data driven site.

  1. Open the QuickStart.cst file found in the directory with this file.
  2. Select your Datasource.
  3. Generate the template.
  4. After Visual Studio Opens, set [DataSource].UI as the startup project.
  5. Run the project.(F5)
  6. This produces a functional website using Dynamic Data, Data Services, and Linq to Sql.
  7. The included csp in the data project can be used to regenerate databse informatin when future changes are made.
  8. The quickstart has various properties that can be manipulalted in order to produce differing base projects, including Language and ProjectType.

Do It Yourself

Use the following steps to get started using the Linq to Sql templates.

  1. Create a new Class Library project in Visual Studio 2008.
  2. Add a new CodeSmith project file to the Visual Studio project.
  3. Add a new Output to the project file for the Dbml.cst template.
  4. Add another Output to the project file for the Entities.cst template.
  5. Optionally, Add an Output for the Managers.cst template.
  6. Set the Sample.csp -> Output Options -> Add Outputs to Project to unchecked.  The templates update the project for you.
  7. Finally, Generate the Outputs. (Figure 5)

QuickStart.cst Template

The QuickStart.cst temlplate is used to create a basic project using Linq to Sql.   The template will create a visual studio solution with up to three included projects:   A Data Project, an Interface Project, and a Test Project.

Properties on the QuickStart.cst template:

Property Description
SourceDatabase The Database that will be accessed by the website.
Language The language that thee project will be generated in.
LaunchVisualStudio Should visual studio launch when the project finishes generating.
Location The root directory of the generated solution.
SolutionName The name of the Visual Studio Solution.
VisualStudioVersion The version of Visual Studio you will be using.
CopyTemplatesToFolder Create a copy of the Linq to Sql Directory and its contents to the data project directory.
DataProjectName The name of the data project directory and project.
IncludeDataServices Include Data Service Files and References in the interface project.
InterfaceProjectName The name of the interface project directory and project.
ProjectType The type of interface project to be created. Can be none.
IncludeTestProject Include a test project in the solution.
TestProjectName The name of the test project directory and project.

Dbml.cst Template

The Dbml.cst template is used to create a LINQ to SQL dbml file.  The file conforms to the Microsoft DbmlSchema.xsd schema.  This is the same document that the LINQ to SQL designer uses.  The generated dbml file from this template can also be edited from the LINQ to SQL designer. 

The template will create a new file if it doesn't exist.  If the file does exist, the template will read it in and update it.  This allows you to make changes to the file and not have it overwrite if the template is re-ran.  However, only some of the attributes are safe from overwriting.  Here is a list of safe attributes.  They will be listed as an xpath.

Safe Attributes to change in the Dbml file ...

Warning: Be aware that the template will drop tables, columns and associations that it did not find in the database.

Properties on the Dbml.cst template:

Property Description
CleanExpression List of regular expressions to clean table, view, column and procedure names.  Any matched text found will be removed from the name.
IgnoreList List of regular expressions used to ignore tables, views and procedures when generating mapping.
IncludeFunctions Include stored procedures and user functions in mapping.
IncludeViews Include views in mapping.
SourceDatabase The source database to generate the dbml file for.
ContextNamespace The namespace to use for the context class file.
EntityNamespace The namespace to use for the entity class files.
Naming Conventions A Menu of options for naming objects in the dbml.
AssociationNaming Add a list suffix or pluralize associations to an object.
EntityNaming Generate entity objects in singular or plural form.
TableNaming The table naming convention followed in the source database.
DbmlFile The path to the dbml file to generate.

Entities.cst Template

The entities template generates the entity classes needed by LINQ.  The classes are generated from a dbml file.  You can modify the names for classes and properties by editing the dbml file.  See Dbml.cst for a list of safe attributes to change in the dbml file.

The template will generate 2 files for every Type in the dbml file.  One file will be the generated partial class that can not be changed as it is overwritten when the template is re-ran.  It will have the following file name... <entity>.Generated.cs

The second file is a partial class that can be modified as it will not be re-generated.  You can implement the partial methods in this file.  Some partial method stubs are created by default. This file will be named... <entity>.cs

If you set the project file property on the template, the generated files will be added to the project.  The file that can not be modified will be hidden under the file that can be changed.

Properties on the Entities.cst template:

Property Description
DbmlFile The path to the dbml file used generate the entities from.
Framework The version of the .Net Framework that is being used. Version 35_1 is necessary for dynamic data and data services attributes.
IncludeDataContract Include serialization attributes on the generated entities. The attributes generated are based on the framework attribute above.
IncludeDataServices Include Data Services attributes on the generated entities.
OutputDirectory The folder to save the generated files.

Managers.cst Template

The manager template is for helping you get started with business logic for the LINQ entities.  The managers will have common queries that are created from keys and indexes on the table.  The manager will also have rules for the entity properties to make sure required fields are not null and that the length of a string does not exceed the max length the column allows.

The template works by creating a second partial class that has a Manager property.  The manager will then have a property for each entity that has a manager. Here is a sample of the syntax for using the managers:

SampleDataContext db = new SampleDataContext();

// use the primary key

Task task = db.Manager.Task.GetByKey(taskId);

// use a foreign key

var myTasks = db.Manager.Task.GetByAssignedID(userId);

// the methods return IQueryable so you can add expressions

var openTasks = db.Manager.Task.GetByStatusID(statusId).OrderBy(t => t.CreateDate);

The manager will add business rules to your entities based on metadata attributes. These rules are based on the same rules found in the DataAnnotations.

private class Metadata

{

    // Only Attributes in the class will be preserved.

    public int OrderId { get; set; }

    [Required]

    [StringLength(20)]

    public string UserId { get; set; }

    [Range (typeof(DateTime), "10-31-2008", "12-25-2200")]

    public System.DateTime OrderDate { get; set; }

.......

}

The manager also provides a business rules engine to your entities. In addition to the default validation rules that are generated, you can add custom rules by implementing the AddRules partial method in the custom entity class.

static partial void AddRules()

{

    // Rule allows the Name property to be a max of 150 characters.

    RuleManager.AddShared<Task>(new LengthRule("Name", 150));

    // Rule that validates the value of the property using regex.

    RuleManager.AddShared<Task>(new RegexRule("Name", ".*"));

    // Rule allows only users in certain security roles to update.

    RuleManager.AddShared<Task>(new UpdateRule(

        new string[] { "Administrator", "Updaters" }));

}

Properties on the Managers.cst template:

Property Description
SourceDatabase The source database to keys and indexes from for generating the manager classes.
Framework The version of the .Net Framework that is being used.
DbmlFile The path to the dbml file used generate the manager classes from.
DataContextFile The location of the DataContext File.
DataContextName The class name of the DataContext that supports the managers.
ManagerDirectory The folder to save the generated manager files.
ManagerNamespace The namespace to use for the generated manager class files.

Queries.cst Template

The queries template is an optional alternative to the manager template.  If you don't want to use the manager framework, you can use this template to generate some common queries for an entity.  While its possible to use both the manger and query templates, they do duplicate some functionality. The template works by generating an extension class for Table<Entity>.  This allows the queries to be off the DataContext.

SampleDataContext db = new SampleDataContext();

Task task = db.Task.GetByKey(1);

This is an example of what the extension class looks like.

/// <summary>

/// The query extension class for Task.

/// </summary>

public static partial class TaskQueryExtension

{

    /// <summary>

    /// Gets an instance by the primary key.

    /// </summary>

    public static Task GetByKey(this Table<Task> entity, int taskID)

    {

        if (entity.Context.LoadOptions == null)

            return Query.GetByKey.Invoke((SampleDataContext)entity.Context, taskID);

        else

            return entity.FirstOrDefault(t => t.TaskID == taskID);

    }

 

    /// <summary>

    /// Gets a query by an index.

    /// </summary>

    public static IQueryable<Task> GetByStatusID(this Table<Task> entity, int statusID)

    {

        if (entity.Context.LoadOptions == null)

            return Query.GetByStatusID.Invoke((SampleDataContext)entity.Context, statusID);

        else

            return entity.Where(t => t.StatusID == statusID);

    }

 

    #region Query

    /// <summary>

    /// A private class for lazy loading static compiled queries.

    /// </summary>

    private static partial class Query

    {

        internal static readonly Func<SampleDataContext, int, Task> GetByKey =

            CompiledQuery.Compile(

                (SampleDataContext db, int taskID) =>

                    db.Task.FirstOrDefault(t => t.TaskID == taskID));

 

        internal static readonly Func<SampleDataContext, int, IQueryable<Task>> GetByStatusID =

            CompiledQuery.Compile(

                (SampleDataContext db, int statusID) =>

                    db.Task.Where(t => t.StatusID == statusID));

 

    }

    #endregion

}

Properties on the Queries.cst template:

Property Description
SourceDatabase The source database to keys and indexes from for generating the manager classes.
DbmlFile The path to the dbml file used generate the query classes from.
QueryDirectory The folder to save the generated query extension files.
ProjectFile The Visual Studio project file to add the generated files to.

Global.cst Template

The global templat is for use specifically with dynamic data projects.  It can be used to generate the global.asax file with the appropriate Data Context and routing.

Property Description
ClassNamespace The namespace for the project.
ContextNamespace The namespace of the datacontext.
DataContextName The name of the data context class.
InlineEditing Default the routing to allow inline editing of tables.

Known Issues

Roadmap

Download

Download the latest release from CodePlex.

History

 

*Breaking change