Differences in Creating the Models
Similar to the DataSet designer, LINQ to SQL's design surface lets you drag tables, views, and stored procedures directly from a DataConnection represented in Visual Studio's Server Explorer. It identifies existing primary keys, primary key/foreign key relationships, and other constraints, and builds them into the model.
You can easily add and remove objects from the model after the fact. However, the model cannot automatically update itself if the database changes. To update the model, you will have to manually remove and re-add items to the model.
One nice LINQ to SQL designer feature is that it recognizes that a class in the model is a single entity. Therefore, by default it automatically attempts to create singular names for tables that have plural names. For example, Contacts
(you can turn off this default setting).
Entity Framework's designer uses a wizard to build the model rather than the drag-and-drop scenario. The designer is also able to update the model from the database—selecting objects that you may not have selected the first time around, or updating the schema when the data store changes. During this update, new fields in tables that already exist in the model are recognized and added as properties to the relevant entity. Most customizations to the CSDL remain intact during an update; however, it overwrites customizations that you may have made to the store schema (SSDL). I have been taking advantage of SSDL model customizations, and this overwrite behavior is definitely frustrating.
Customizing DataSets, LINQ to SQL, and Entity Data Models
|Author's Note: Unlike the LINQ to SQL designer, the EDM Wizard does not automatically fix plural entity names as it creates them, so that's one of the first things I do to a newly created model.
You can, of course, make modifications to the structures of a strongly typed DataSet, the LINQ to SQL model, and the Entity Data Model. However, the degree of customization differs vastly between the three; it is here that you can see the true power of the Entity Data Model.
Cosmetic Changes to Classes
There are some basic features allowed by both the models and the strongly typed DataSet. For example, you can rename any of the Entities/DataTables or Properties/DataColumns so the names make more sense to you. This is a great convenience, because it lets you change names without having to pester the DBA or affecting other code. You can also remove properties/columns and create keys and relationships in the DataSet designer, LINQ to SQL or EDM.
LINQ to SQL and the EDM both let you do something that is not possible in a database—build inheritance directly into the models. LINQ to SQL supports Table per Hierarchy (TPH) inheritance, while Entity Framework supports TPH as well as Table per Type (TPT) and Table per Concrete Type (TPC) inheritance. Some recent blog posts and a sample on the ADO.NET Team's code gallery page demonstrate how to pull off TPT inheritance in LINQ to SQL as well.
Table per Hierarchy (TPH)
|Figure 6. Table per Hierarchy Inheritance: In LINQ to SQL, you can define Table per Hierarchy inheritance using one of the table properties as a discriminator. Here, WebOrder inherits from SalesOrderHeader where OnLineOrderFlag = True.|
TPH inheritance lets you create a class hierarchy from a single table in the database. As an example, the AdventureWorks' SalesOrderHeader
table has a Boolean field named OnlineOrderFlag
. In both LINQ to SQL and the EDM, you can treat the online orders as a separate entity that inherits from SalesOrderHeader. The method for doing this is a bit different in the two models, but the effect is the same.
shows the WebOrder class, which inherits from SalesOrderHeaders in LINQ to SQL. The Inheritance object's property window is also shown. The OnlineOrderFlag
property discriminates between regular SalesOrderHeader types and online orders. The base type, SalesOrderHeader, will be populated by orders using OnlineOrderFlag = False
, while the derived type, WebOrder, is defined by OnlineOrderFlag = True
. Unfortunately, you can't use Null
as a discriminator value because the discriminator doesn't have a way to represent "not-null".
You can use both base and inherited entities in LINQ to SQL queries. For example, this Visual Basic query returns only WebOrders:
When you create new WebOrder objects, the discriminator value gets filled automatically; when you insert the object, the OnlineOrderFlag
will already be set to True
With the Entity Data Model, the inheritance is built in nearly the same way, although EDM uses conditional mapping to differentiate between the base class and the derived class.
EDM's Other Types of Inheritance
Additional EDM Mapping Capabilities
- Table per Type (TPT) inheritance describes a scenario where there are multiple tables in the database that can be represented as base and inherited types in the Entity Data Model. A simple example of this would be a database with a Person table and an Employees table that extends the data available in the Employees table, perhaps with fields such as Hire Data. In the Entity Data Model it is possible to create an inheritance relationship between the two.
- Table per Concrete Type (TPC) is a less common scenario supported by the Entity Data Model. You'll find this useful when a table with duplicate schema exists that contains a subset of data. For example, you may have a Product table accumulating so many discontinued products that the DBA split the discontinued products off into their own table. The mapping is still able to represent the DiscontinuedProduct entity type as inheriting from Product.
|Figure 7. Common Properties: The circled areas show Customer and Employee entities before centralizing the Address info into a complex type.|
The Entity Data Model supports two other types of complex mapping as well.
- Entity Splitting: It is possible to create an entity whose properties come from multiple tables that have one-to-one relationships; this is referred to as "splitting an entity".
- Complex Types: You use a ComplexType to define common properties among various entities. For example, if you have a number of entities that each have address information, such as in Figure 7, you can create a complex type that encapsulates these properties:
<Property Name="Address" ...
<Property Name="City" ...
<Property Name="Region" ...
<Property Name="PostalCode" ...
<Property Name="Country" ...
<Property Name="Phone" ...
<Property Name="Fax" ...
You can then use that type as a property for the entities in place of the scalar properties that it encapsulates.
While the column names of the tables that these entities map to are different, the mappings resolve the differences. The documentation contains more information about constructing and mapping complex types.
Microsoft offers quite a number of other ways to customize an Entity Data Model. You make some of these customizations in the mapping layer and others in the layer that represents the data store. The latter lets you add "virtual" tables, views, and queries to the model that don't truly exist in the data.
Unfortunately, some of the model customization possibilities (such as complex types) did not make it into the current version of the designer. You can still add these customizations manually, but after they exist in the model, you won't be able to open the model in the designer. Some customizations don't prevent you from opening the model in the designer, yet they don't show up in design view. For the most part, the lack of designer support for some modeling features isn't critical, because the unsupported features aren't commonly used.