Persistent Entities
Modeling your persistent entities (classes) is the same experience as most any other modeling tool – you drag the class onto the design surface from the toolbox, name it, and start adding properties. You won’t model operations (methods), though, since our focus is on creating code for Entity Framework. If you want to add operations, you’ll do that in partial classes.
Adding an Entity
With the designer open, find the Entity tool in your toolbox. Click and hold down the left button, then drag it to the design surface.
You should see a new class appear on the design surface:
You can change the width of the entity on the designer to make things more readable. Height is automatic and can’t be changed manually - it will be as tall as needed to show all the properties. But the entity may be collapsed down to its name bar by clicking the chevron at the top right of its display. When collapsed, it may be expanded back to its original size by clicking the chevron again.
You can collapse and expand the Properties
and Associations
compartments by clicking the small +
(or -
) icon to the
left of their gray title bars.
A quick note about the Associations
compartments. You’ll note that they’re divided into Association Sources
and
Association Targets
. This really isn’t a big distinction … it has to do with how you started drawing the association and is
an artifact of the Microsoft Modeling SDK. One day (hopefully) they’ll be combined into just Associations
, but that will take
a refactoring of the inner structure of the designer and is a Big Deal. There’s more about Associations later.
Removing an Entity
To remove an entity, simply select it (from either the design surface or the model explorer) and hit the Delete key. It will be removed from the model completely without confirmation, as will its associations with other classes. If you do this by accident, you can undo it (Ctrl-Z or Edit/Undo from the menu).
If that entity is the superclass (base class) for other entities, you’ll be asked if you want to push its attributes and associations down to those other entities prior to its removal.
Entity Properties
Selecting the entity from either the design surface or the model explorer allows you to edit its various properties:
Property | Description |
---|---|
Code Generation | |
Abstract | Boolean. If true, an abstract class will be generated for this entity. |
Auto Property Default | Boolean. If true, Properties for this class will be created as AutoProperties with just bare getters and setters. Otherwise, they'll have a backing field and code in the getters and setters to move the `value` parameters. In this case, you'll also have partial methods available to modify the results. |
Base Class | String. The name of the class pointed to by the `Inheritance` link in the designer. You can change it here and the link will change in the designer.</a>. |
Concurrency | String. Overrides the default concurrency handling strategy. Values are 'Optimistic' and 'None'. See Handling Concurrency with the Entity Framework 6 in an ASP.NET MVC 5 Application. |
Custom Attributes | String. Attributes generated in the code for this element - anything here will be generated verbatim into the code in the class definition. |
Custom Interfaces | String. Any custom interface(s) this entity should implement. If more than one, separate them with commas - anything here will be generated verbatim into the code in the class definition. |
DbSet Name | String. The name of the DbSet property in the DbContext for this class. |
Generate Code | Boolean. If true (the default), code will be generated for this class. If false, it is assumed to be referenced from another assembly. |
Implement INotifyPropertyChanged | Boolean. If true, will generate code for easy implementation of property change notifications. |
Name | String. The name of this class. |
Namespace | String. The namespace for this class. |
Output Directory | String. The project directory for this class's generated file. Overrides the default Entity Output Directory. |
Database | |
Database Schema | String. The database schema name for the table that will back this class. |
Is Dependent Type | Boolean. If true, this type will be generated as a "complex" (EF6) or "owned" (EFCore) type. |
Table Name | String. The name of the table that will back this class. |
Display | |
Fill Color | Color. The color for entity's banner on the design surface. |
Visible | Boolean. If true, the entity will be visible on the design surface. If false, will be hidden. Can also be toggled via the context menu when the entity is selected. |
Documentation | |
Comment Detail | String. XML comment <Remarks> section |
Comment Summary | String. XML comment <Summary> section |
Context Menu
Right-clicking on an entity displays a Visual Studio context menu with some new choices pertinent to that entity.
Menu choice | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Add | One submenu choice, Property, adds a property to the entity. | ||||||||||
Collapse | Available when the entity is fully expanded, this action hides the properties so that only the title is visible. | ||||||||||
Expand | Available when the entity is fully collapsed, this action shows the properties, revsersing the _Collapse_ action. | ||||||||||
Cut, Copy, Paste, Delete | You can cut or copy, then paste, classes and enums. The pasted elements will be adjusted so that they don't violate any rules (such as two elements not having the same name), but otherwise the properties will stay the same. If no classes or enums are selected in the designer, the cut and copy options will be disabled. If no classes or enums are in the clipboard, the paste option will be disabled. | ||||||||||
Validate | Checks the currently selected entity against the validation rules built into the designer. Errors or warnings are displayed in Visual Studio's Error List window. If no element is selected, this validates the design surface itself. | ||||||||||
Validate All | Checks all model elements against the afore mentioned validation rules. Errors or warnings are displayed in Visual Studio's Error List window. | ||||||||||
Hide Selected Elements | Hides the currently selected elements on the diagram. Any lines to or from those elements will be hidden as well. This does not remove the entity from the model, only makes it invisible in the diagram. Useful for tidying up a diagram that would otherwise be unreadable due to, for example, a common base class that all other classes inherit from. If no entity is selected, this option will be disabled. | ||||||||||
Show Hidden Elements | Unhides any elements that were previously hidden, along with their association or inheritance lines. If no elements are hidden, this option will be disabled. | ||||||||||
Add properties via Code | Displays a dialog that lets you add multiple properties using the designer's custom property syntax. See "Adding properties via code" for more details. | ||||||||||
Save as Image | Will save the entire diagram as an image. Format choices are BMP, GIF, JPG, PNG, TIFF and WMF. | ||||||||||
Expand Selected Elements | Expands any selected elements that are collapsed to their headers. | ||||||||||
Collapse Selected Elements | Collapses any elements down to their headers. | ||||||||||
Merge Unidirectional Associations | Available when you have two Unidirectional Associations selected that both connect the same classes. Turns them into one Bidirectional Association (the inverse of Split Bidirectional Association, below). | ||||||||||
Split Bidirectional Association | Available when you have a Bidirectional Association selected. Turns it into two Unidirectional Associations (the inverse of Merge Unidirectional Associations, above.). | ||||||||||
Select | One of the features of the Visual Studio property editor is the ability to edit properties of multiple items if they share that property. This submenu gives you the ability to select model elements by type so that you can conveniently edit properties of those elements together (e.g., setting the color of multiple classes all at once). If the pertinent element type isn't present in the designer, that option will be disabled.
| ||||||||||
Properties | Switches focus to the Properties window. |
INotifyPropertyChanged
You can optionally implement the standard INotifyPropertyChanged
interface, especially useful for data binding in WinForms applications. By changing that property to True
(by
default it’s False
), the standard T4 templates will generate code you can customize by implementing a partial method.
The shape on the diagram will change to have a dashed blue border, helping you immediately see which classes will generate
change notification code. Since INotifyPropertyChanged
requires a bit of logic, the properties of that class won’t be
autoproperties. Each property will be set to AutoProperty = False
when Implement INotifyPropertyChanged
is set
to True
; if you set AutoProperty
to True
while indicating that you want INotifyPropertyChanged
code, you’ll
get a warning on model validation indicating that said property won’t participate in change notification since it’s an
autoproperty.
The generated code for a property will look like the following:
/// <summary>
/// Backing field for Foo
/// </summary>
protected string _Foo;
/// <summary>
/// When provided in a partial class, allows value of _Foo to be changed before setting.
/// </summary>
partial void SetFoo(string oldValue, ref string newValue);
/// <summary>
/// When provided in a partial class, allows value of _Foo to be changed before returning.
/// </summary>
partial void GetFoo(ref string result);
public string Foo
{
get
{
string value = _Foo;
GetFoo(ref value);
return (_Foo = value);
}
set
{
string oldValue = _Foo;
SetFoo(oldValue, ref value);
if (oldValue != value)
{
_Foo = value;
OnPropertyChanged();
}
}
}
public virtual event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Note that this interface doesn’t give you sufficient detail to know how a property changed, only which
property changed; Microsoft never intended it to. Its initial purpose was to support data binding, so it’s an
important part of .NET, but you need more info to handle property change notifications outside of a data binding
context. You have that in the code that’s generated when you set AutoProperty = False
in the model for an entity’s
property.
Any generated property with a backing field gives you the chance to do work (log, massage the return value, etc.)
in their get
and set
methods by implementing the corresponding GetXXX
and SetXXX
partial functions. In those
partials, you have access to the old and new values (for the SetXXX
method) and can implement whatever logging, etc.
you need. Therefore, when tracking changes, the generated OnPropertyChanged
method will be used when the .NET Framework
finds it appropriate but your work should go in the SetXXX
partial method.