Create Custom Features for Database Projects

You can extend existing database project types by adding your own features. For example, you can create a feature that does something every time that a database project is loaded or saved. You can also create your own database schema provider and supporting project system. However, that type of extensibility is not covered in this content.

Common Tasks

Common Tasks

Supporting Content

Learn more about the extensibility points: You can read about the design of database project extensibility.

  • Goals of Project Extensibility

  • Component Model Assemblies

  • Extensibility Points

  • Database Project Lifecycle

  • Error Management

Create a sample project feature: Learn the steps that are required to create a custom project feature that displays a dialog box when a database project is loaded. If you follow these walkthroughs, you will:

  • Create a Visual Studio package.

  • Customize that package to create a database project feature.

  • Build, install, and test your new project feature.

Install a custom project feature: After you create and build a project feature, you must install it before Visual Studio will recognize it.

Goals of Project Extensibility

The major goals for the database project extensibility features in Visual Studio 2010 are as follows:

  • Expose major components through interfaces
    This approach keeps the project system consistent with the schema model, by using interfaces instead of abstract classes. A single concrete class is expected to implement many interfaces.

  • Features are created by the extensibility manager
    Features are responsible for major parts of the system including Solution Explorer, Schema View, project upgrade, and project properties.

  • Features can be extended
    Features can use the extensibility manager, XML files, registry or other approaches to provide that extensibility.

  • Services are exposed through their own interface
    DataPackage implements IServiceProvider. Any cross-talk between features should be handled through servicing at these levels. You should not expose your feature as the service. Instead, create a new interface, a wrapper class, and then expose the wrapper as the service.

  • Events drive the project system
    The DataPackage and the ProjectNode() offer events that enable features to drive the project system. In addition, features can provide events through their service interfaces. In some cases, you might decide to use a delegate. To decide which feature handles the action, consider using an event approach where the features could interact, based on priority.

  • Do not rely on the ordering of listeners
    If the order of listeners to an event is important, then consider creating a Pre or Post event or consider adding a priority property to the class derived from EventArg.

Component Model Assemblies

The following assemblies provide the database project system in Visual Studio.

  • Microsoft.VisualStudio.Data.Schema.Package.dll
    The base project system and provides for feature bootstrapping and eventing. This includes database-agnostic features, such as scripts.

  • Microsoft.VisualStudio.Data.Schema.PackageUI.dll
    The satellite assembly for the database-agnostic package.

  • Microsoft.VisualStudio.Data.Schema.Package.Sql.dll
    The SQL Server-specific features, editors, and tool windows for Visual Studio.

  • Microsoft.VisualStudio.Data.Schema.Package.SqlUI.dll
    The satellite assembly for the SQL Server-specific features, editors, and tool windows.

Extensibility Points

You can extend the follow points of the database project system:

Database Project Lifecycle

Every database project file (.dbproj) contains a property named "DSP" indicating the specific DatabaseSchemaProvider that handles this project when it is opened in Visual Studio. The project system creates an extension manager by using this DSP and from that constructs all the project system contributors and project features. Each feature receives an Initialize event so that it can initialize and root itself into the project system by listening to events.

The following events are raised during project open/close and save:

  • NewProjectCreated
    This event occurs when a project is first created. You can handle this event to display wizards or setup dialog boxes.

  • ProjectOpening
    The project is opening. You can handle this event to add any services to the IDatabaseProjectNode.

  • ProjectOpened
    This event occurs when all services were added and the project has completed opening. However, project will not yet have completed deserializing its previous state. The TaskHost and the DataSchemaModel will be NULL until the ProjectLoaded event is sent.

  • ProjectLoaded
    The project is fully loaded. The TaskHost and the DataSchemaModel are ready for use.

  • ProjectClosing
    The project is closing. This is a good opportunity to persist any state information that is outside the project file.

  • ProjectClosed
    The project is closed.

  • ProjectSaving
    The project is performing a save operation. You can use this as an opportunity to make sure that your feature is in a state for its persistence to be stored.

  • ProjectSaved
    The project has been saved.

Error Management

Every project has one ErrorManager. Some errors are persisted to the .dbmdl file and other errors are not. This is controlled through the AddPersistedCategory class. By default these categories are persisted: ModelCategory, ValidationAtBuildCategory, and ValidationOnIdleCategory. If you add another persisted category you will have to handle the project reload and verify and manage your errors. Remember that although the project was closed, the user could have edited the .dbproj file to remove a file for which you are reporting an error. It would be very confusing to users to report an error in the project when no such file exists.

Database error objects are added to the ErrorManager in specific categories. The idea is that project features can manage the lifetime of their errors through the lifetime of their category. If you are concerned about category names conflicting with other features then use a GUID as the name. The ErrorManager defines several built-in categories including:

  • DefaultCategory
    This category is designed for you to use for errors whose lifetimes are equal to the lifetime of the project. Therefore, for example, errors which occur during project load are added into this category.

  • ModelCategory
    This category should be used by the schema manager when it encounters errors such as parser errors.

Create Custom Database Refactoring Types or Targets

Create and Register Additional Rules for Analyzing Database Code

Generate Specialized Test Data with a Custom Data Generator

Define Custom Conditions for Database Unit Tests

Customize Database Build and Deployment by Using Build and Deployment Contributors

See Also

Concepts

Extending the Database Features of Visual Studio