Properties
Properties can be added to entities, and will become class properties backed with database columns upon code generation. They’re generated with reasonable defaults, but can be easily modified to suit your use cases.
Adding a Property
There are a few ways to add a property to an entity:
- Right click the Properties category heading right below the name of the entity on the designer and choose Add new Property .
- Right click the name of the entity on the designer and select Add, then Property from its context menu.
- With the Properties category heading selected on the designer, hit the Insert key
- With any property selected in the entity on the designer, hit Enter.
- Right click the entity in the Model Explorer and select Add New Property.
A new property will be added to the entity and you’ll have the opportunity to change its name from the default generated name. An advanced feature of the designer also gives you the opportunity to change its type, whether or not it’s an identity field, and whether or not its value is required to be other than the type’s default value at runtime (i.e., a required property). See more about this below.
Removing a Property
To remove a property, simply select it (on the designer or the Model Explorer) and hit the Delete key. It will be removed from the model completely without confirmation.
Property Properties
Selecting a property gives you access to its properties in the Property window. Those are:
Property | Description |
---|---|
Code Generation | |
Abstract | Boolean. If false, this is a normal property. If true, it will be generated as an abstract property and the entity will be marked as abstract as well. Note that setting it from true to false does not reset the entity's Abstract property back to false. |
Auto Property | Boolean. If false, generates a backing store field with a partial method to hook getting and setting the property. If true, generates a simple auto property. |
Custom Attributes | String. Attributes generated in the code for this element - anything here will be generated verbatim into the code in the class definition. |
Display Text | String. Will cause the generation of a [Display(Name="<text>")] attribute tag in the code. |
Implement INotifyPropertyChanged | Boolean. If true, will cause this property to not be an autoproperty and will add code to implement INotifyPropertyChanged to the setter. If false, that code won't be generated, and the AutoProperty value can be set back to true (setting this value to false won't change AutoProperty back). |
Initial Value | String. Value for attribute when first created. Will be validated to ensure entry is appropriate for the property's type |
Name | The name of the property. Must be a valid C# symbol. |
Persistent | Boolean. If true, Attribute will be stored in persistent storage |
Read Only | Boolean. If true, no setter will be generated. Only valid for transient public properties. |
Required | Boolean. If true, cannot be null (or the default value for the property type, if not nullable) |
Setter Visibility | String. Visibility for property setter; getter is public. Valid entries are public and protected. This setting is unavailable if the property is an Identity and autogenerated. |
Type | String. Type of this attribute. Select from list of valid types. If you pick a type that can't be used as an identity, the Is Identity and Identity Type properties will be removed. |
Virtual | Boolean. If true, property will be generated with the 'virtual' keyword |
Database | |
Column Name | String. The name of the backing column in the database |
Column Type | String. The data type for column in the database. Use default to let Entity Framework decide. Overrides here should be valid for the database being used. No error checking occurs to detect compatability between this value and the property's type |
Identity Type | String. If this property is an identity, how the value is generated? Choices are AutoGenerated (to let EF create it for you), Manual (doing it yourself) or None (this isn't an identity property) |
Indexed | Boolean. If true, this property will create an index in the database. For multi-property indices, see below. |
Indexed Unique | Boolean. If indexed and this is true, a unique index will be created in the database using this property |
Is Concurrency Token | Boolean. If true, this property serves as the concurrency value for the class |
Is Identity | Boolean. If true, this attribute represents the identity of the object. Will automatically set Indexed and Indexed Unique to true. Note that if you want a multi-property identity (or, in database terms, a multi-column primary key), you can set this value to true for more than one property in the entity. |
Documentation | |
Comment Detail | String. XML comment <Remarks> section |
Comment Summary | String. XML comment <Summary> section |
String Properties | |
Max Length | Integer. Maximum length of the string, 0 for no max length |
Min Length | Integer. Minimum length of the string, 0 for no min length. If non-zero, must be less than or equal to Max Length. |
String Type | String. If not empty, will create a HTML5 attribute annotation for this attribute. Valid values are None, Color, Date, DateTime, Email, Month, Number, Range, Search, Telephone, Time, URI, Week, and Password. |
Creating a multi-property index
There isn’t any direct support in the designer for adding an index that spans more than one property, but that doesn’t mean it can’t be done.
Just to be clear, we’re not talking about identity properties here. For identity, setting the Is Identity
flag for a property will
cause it to be used as part of the entity’s identity, and that’s for one property or more than one. This discussion is about
plain old indices. With the designer, you can have any property be indexed (by setting its Indexed
flag to true), but
that creates an index for that property only; if you want to create one index for a set of properties, you’ll have to go beyond
the designer.
To do that, implement the OnModelCreatedImpl
method in your context’s partial class. There, you can add a method to
create your index on however many properties you need. Something like
void OnModelCreatedImpl(System.Data.Entity.DbModelBuilder modelBuilder) {
modelBuilder.Entity<Item>().HasIndex((Item b) => new { b.column1, b.column2, b.column3 });
}
Context Menu
Right-clicking on a property displays a Visual Studio context menu with some new choices pertinent to that property.
Menu choice | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Add new Property | Adds a property to the entity. | ||||||||||
Edit | Activates in-diagram editing for the property name (and other attributes using the designer's custom property syntax) | ||||||||||
Cut, Copy, Paste | You can cut or copy, then paste, properties. Pasting can be to the same entity or to other entities. 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 properties are selected in the designer, the cut and copy options will be disabled. If no properties are in the clipboard, the paste option will be disabled. | ||||||||||
Delete | The selected property will be removed from the entity. | ||||||||||
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. | ||||||||||
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. | ||||||||||
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. |
Adding Properties via Code (custom property syntax)
You can quickly add a group of properties as text, a great time saver for those cases where you have existing classes that you want to make persistent and add to the model.
The designer exposes a custom property syntax that allows you to specify a property’s:
- Setter visibility
- Name
- Type
- Required status
- Minimum length (if it’s a string)
- Maximum length (if it’s a string)
- Initial value
- Whether it’s the identity property for its entity
All of these are optional except for Name. Some details:
Element | Default | Notes |
Name | Required | |
Type | "string" | Can be CLR type or built-in type (e.g., Int32 or int) |
Required | false | Indicated by the '?' symbol appended to the Type |
Minimum Length | 0 | Indicated by a decimal number in brackets. If present, must be followed by hyphen ('-') and the maximum length. A zero (0) means no minimum length. |
Maximum Length | 0 | Indicated by a decimal number in brackets. A zero (0) means no maximum length. |
Initial Value | Indicated by an equal sign ('=') followed by some value | |
Is Identity | false | Indicated by the '!' symbol appended to the Name |
The syntax is:
<Visibility> <Type><?><[MinLength-MaxLength]> <Name><!> <= Value>
or
<Visibility> <Name><!> : <Type><?><[MinLength-MaxLength]> <= Value>
Examples:
The following all declare a required string property with no length restrictions named foo:
foo
string foo
public string foo
foo: string
public foo: string
To make it an optional value:
string? foo
public string? foo
foo: string?
public foo: string?
Let’s make it optional and restrict it to 50 characters:
string?[50] foo
public string?[50] foo
foo: string?[50]
public foo: string?[50]
Or ensure that it’s between 10 and 50 characters
string?[10-50] foo
public string?[10-50] foo
foo: string?[10-50]
public foo: string?[10-50]
(A bit more on this: MinLength isn’t needed if you don’t care about it, so [50] is perfectly valid as a MaxLength specification. You would use [10-0] to say the MinLength is 10 but there is no MaxLength, since having just one number in the brackets is interpreted as a MaxLength. [0-50] is pefectly valid, but unnecessary, since [50] would do. [50-10] is right out - you’ll get an error trying to do that.
You might be wondering: if I specify a minimum length, does that mean it’s required? The model won’t automatically set the Required attribute if it sees a Min Length, since that would mean that it’s needed at object construction time, and you may not intend that to be true.)
If we wanted to set it up in the entity’s constructor with an initial value:
foo = "some value"
string foo = "some value"
public string foo = "some value"
foo: string = "some value"
public foo: string = "some value"
(note that, while making a property optional and giving it a initial value is possible, it has limited use cases)
To add an identity property:
int foo!
public int foo!
foo!: int
public foo!: int
Let’s make foo a Nullable<Int64>
and have its setter inaccessible by outside code:
protected long? foo
protected foo: long?
To edit the properties as text, select the entity and right-click to get its context menu. Choose Add properties via Code and you’ll see a small window pop up with the current properties:
Add, edit or remove text as required - when you click OK, all the properties will be replaced by the parsed values of the text in that window. Any unrecognized values will be discarded.
You’ll note that one of the options is for the text to be a list of valid C# property declarations, so if you have classes that you want to add to the model, you’ll be able to copy their property declarations and paste them in here. Any lines with curly braces in them will be truncated at the first open brace. Trailing semicolons are discarded as well.
Let’s say you had an Address class in your code and wanted to add it to your persistent entity model.
public class Address
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string StateProvince { get; set; }
public string PostalCode { get; set; }
}
You could add the class to the designer and open the Add properties via Code window. Copy and paste the properties from your class into this window and click OK.
When you click OK, the Address class is updated with the new properties.
A few things to notice:
- We duplicated the
Id
property, since it was already in the entity and we didn’t delete it before pasting. When the text was parsed and the properties created, that duplicate was discarded. A warning appeared in Visual Studio’s error list letting us know that it was discarded and why. - The
{ get; set; }
blocks were discarded, as was the semicolon (;
) from the one property initially presented. - We added properties using CLR types (
int
andstring
), but they were added to the model as object types (Int32
andString
). - The properties were added as required properties! C# syntax doesn’t (unless you’re using C# 8.0) have a way to indicate that an object is nullable or not.
Since we didn’t edit the code we pasted in, no
?
indicators were present to tell the parser that this isn’t a required property. Note that, even if we had C# 8.0 available, the designer’s property syntax purposely doesn’t fit with C# non-nullable object syntax. That’s to make you review what you’ve entered and think about doing the right thing for your model!