Monday, February 16, 2015

Entity Framework Tutorial VOLUME I

Connections and Models


This topic covers how Entity Framework discovers which database connection to use, and how you can change it. Models created with Code First and the EF Designer are both covered in this topic.
Typically an Entity Framework application uses a class derived from DbContext. This derived class will call one of the constructors on the base DbContext class to control:
How the context will connect to a database—i.e. how a connection string is found/used
Whether the context will use calculate a model using Code First or load a model created with the EF Designer
Additional advanced options
The following fragments show some of the ways the DbContext constructors can be used.
Use Code First with connection by convention
If you have not done any other configuration in your application, then calling the parameterless constructor on DbContext will cause DbContext to run in Code First mode with a database connection created by convention. For example:
namespace Demo.EF 
    public class BloggingContext : DbContext 
    { 
        public BloggingContext() 
        // C# will call base class parameterless constructor by default 
        { 
        } 
    } 
}
In this example DbContext uses the namespace qualified name of your derived context class—Demo.EF.BloggingContext—as the database name and creates a connection string for this database using either SQL Express or LocalDb. If both are installed, SQL Express will be used.
Visual Studio 2010 includes SQL Express by default and Visual Studio 2012 includes LocalDb. During installation, the EntityFramework NuGet package checks which database server is available. The NuGet package will then update the configuration file by setting the default database server that Code First uses when creating a connection by convention. If SQL Express is running, it will be used. If SQL Express is not available then LocalDb will be registered as the default instead. No changes are made to the configuration file if it already contains a setting for the default connection factory.
Use Code First with connection by convention and specified database name
If you have not done any other configuration in your application, then calling the string constructor on DbContext with the database name you want to use will cause DbContext to run in Code First mode with a database connection created by convention to the database of that name. For example:
public class BloggingContext : DbContext 
    public BloggingContext() 
        : base("BloggingDatabase") 
    { 
    } 
}
In this example DbContext uses “BloggingDatabase” as the database name and creates a connection string for this database using either SQL Express (installed with Visual Studio 2010) or LocalDb (installed with Visual Studio 2012). If both are installed, SQL Express will be used.
Use Code First with connection string in app.config/web.config file
You may choose to put a connection string in your app.config or web.config file. For example:
<configuration> 
  <connectionStrings> 
    <add name="BloggingCompactDatabase" 
         providerName="System.Data.SqlServerCe.4.0" 
         connectionString="Data Source=Blogging.sdf"/> 
  </connectionStrings> 
</configuration>
This is an easy way to tell DbContext to use a database server other than SQL Express or LocalDb — the example above specifies a SQL Server Compact Edition database.
If the name of the connection string matches the name of your context (either with or without namespace qualification) then it will be found by DbContext when the parameterless constructor is used. If the connection string name is different from the name of your context then you can tell DbContext to use this connection in Code First mode by passing the connection string name to the DbContext constructor. For example:
public class BloggingContext : DbContext 
    public BloggingContext() 
        : base("BloggingCompactDatabase") 
    { 
    } 
}
Alternatively, you can use the form “name=<connection string name>” for the string passed to the DbContext constructor. For example:
public class BloggingContext : DbContext 
    public BloggingContext() 
        : base("name=BloggingCompactDatabase") 
    { 
    } 
}
This form makes it explicit that you expect the connection string to be found in your config file. An exception will be thrown if a connection string with the given name is not found.
Database/Model First with connection string in app.config/web.config file
Models created with the EF Designer are different from Code First in that your model already exists and is not generated from code when the application runs. The model typically exists as an EDMX file in your project.
The designer will add an EF connection string to your app.config or web.config file. This connection string is special in that it contains information about how to find the information in your EDMX file. For example:
<configuration>  
  <connectionStrings>  
    <add name="Northwind_Entities"  
         connectionString="metadata=res://*/Northwind.csdl|  
                                    res://*/Northwind.ssdl|  
                                    res://*/Northwind.msl;  
                           provider=System.Data.SqlClient;  
                           provider connection string=  
                               &quot;Data Source=.\sqlexpress;  
                                     Initial Catalog=Northwind;  
                                     Integrated Security=True;  
                                     MultipleActiveResultSets=True&quot;"  
         providerName="System.Data.EntityClient"/>  
  </connectionStrings>  
</configuration>
The EF Designer will also generate code that tells DbContext to use this connection by passing the connection string name to the DbContext constructor. For example:
public class NorthwindContext : DbContext 
    public NorthwindContext() 
        : base("name=Northwind_Entities") 
    { 
    } 
}
DbContext knows to load the existing model (rather than using Code First to calculate it from code) because the connection string is an EF connection string containing details of the model to use.
Other DbContext constructor options
The DbContext class contains other constructors and usage patterns that enable some more advanced scenarios. Some of these are:
You can use the DbModelBuilder class to build a Code First model without instantiating a DbContext instance. The result of this is a DbModel object. You can then pass this DbModel object to one of the DbContext constructors when you are ready to create your DbContext instance.
You can pass a full connection string to DbContext instead of just the database or connection string name. By default this connection string is used with the System.Data.SqlClient provider; this can be changed by setting a different implementation of IConnectionFactory onto context.Database.DefaultConnectionFactory.
You can use an existing DbConnection object by passing it to a DbContext constructor. If the connection object is an instance of EntityConnection, then the model specified in the connection will be used rather than calculating a model using Code First. If the object is an instance of some other type—for example, SqlConnection—then the context will use it for Code First mode.
You can pass an existing ObjectContext to a DbContext constructor to create a DbContext wrapping the existing context. This can be used for existing applications that use ObjectContext but which want to take advantage of DbContext in some parts of the application.
Connection Resiliency / Retry Logic (EF6 onwards)
Applications connecting to a database server have always been vulnerable to connection breaks due to back-end failures and network instability. However, in a LAN based environment working against dedicated database servers these errors are rare enough that extra logic to handle those failures is not often required. With the rise of cloud based database servers such as Windows Azure SQL Database and connections over less reliable networks it is now more common for connection breaks to occur. This could be due to defensive techniques that cloud databases use to ensure fairness of service, such as connection throttling, or to instability in the network causing intermittent timeouts and other transient errors.
Connection Resiliency refers to the ability for EF to automatically retry any commands that fail due to these connection breaks.
Execution Strategies
Connection retry is taken care of by an implementation of the IDbExecutionStrategy interface. Implementations of the IDbExecutionStrategy will be responsible for accepting an operation and, if an exception occurs, determining if a retry is appropriate and retrying if it is. There are four execution strategies that ship with EF:
DefaultExecutionStrategy: this execution strategy does not retry any operations, it is the default for databases other than sql server.
DefaultSqlExecutionStrategy: this is an internal execution strategy that is used by default. This strategy does not retry at all, however, it will wrap any exceptions that could be transient to inform users that they might want to enable connection resiliency.
DbExecutionStrategy: this class is suitable as a base class for other execution strategies, including your own custom ones. It implements an exponential retry policy, where the initial retry happens with zero delay and the delay increases exponentially until the maximum retry count is hit. This class has an abstract ShouldRetryOn method that can be implemented in derived execution strategies to control which exceptions should be retried.
SqlAzureExecutionStrategy: this execution strategy inherits from DbExecutionStrategy and will retry on exceptions that are known to be possibly transient when working with SqlAzure.
Note:Execution strategies 2 and 4 are included in the Sql Server provider that ships with EF, which is in the EntityFramework.SqlServer assembly and are designed to work with SQL Server.
Enabling an Execution Strategy
The easiest way to tell EF to use an execution strategy is with the SetExecutionStrategy method of the DbConfiguration class:
public class MyConfiguration : DbConfiguration 
    public MyConfiguration() 
    { 
        SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy()); 
    } 
}
This code tells EF to use the SqlAzureExecutionStrategy when connecting to SQL Server.
Configuring the Execution Strategy
The constructor of SqlAzureExecutionStrategy can accept two parameters, MaxRetryCount and MaxDelay. MaxRetry count is the maximum number of times that the strategy will retry. The MaxDelay is a TimeSpan representing the maximum delay between retries that the execution strategy will use. 
To set the maximum number of retries to 1 and the maximum delay to 30 seconds you would execue the following:
public class MyConfiguration : DbConfiguration 
    public MyConfiguration() 
    { 
        SetExecutionStrategy( 
            "System.Data.SqlClient", 
            () => new SqlAzureExecutionStrategy(1, TimeSpan.FromSeconds(30))); 
    } 
}
The SqlAzureExecutionStrategy will retry instantly the first time a transient failure occurs, but will delay longer between each retry until either the max retry limit is exceeded or the total time hits the max delay.
The execution strategies will only retry a limited number of exceptions that are usually tansient, you will still need to handle other errors as well as catching the RetryLimitExceeded exception for the case where an error is not transient or takes too long to resolve itself.
Limitations
There are some known limitations when using ExecutionStrategies. If you want to use user initiated transactions or streaming instead of buffered queries then you should read more here
Code-Based Configuration (EF6 onwards)
Configuration for an Entity Framework application can be specified in a config file (app.config/web.config) or through code. The latter is known as code-based configuration.
Configuration in a config file is described in a separate article. The config file takes precedence over code-based configuration. In other words, if a configuration option is set in both code and in the config file, then the setting in the config file is used.
This page covers the following topics:
Using DbConfiguration
Example
Moving DbConfiguration
Setting DbConfiguration explicitly
Overriding DbConfiguration
Using DbConfiguration
Code-based configuration in EF6 and above is achieved by creating a subclass of System.Data.Entity.Config.DbConfiguration. The following guidelines should be followed when subclassing DbConfiguration:
Create only one DbConfiguration class for your application. This class specifies app-domain wide settings.
Place your DbConfiguration class in the same assembly as your DbContext class. (See the Moving DbConfiguration section if you want to change this.)
Give your DbConfiguration class a public parameterless constructor.
Set configuration options by calling protected DbConfiguration methods from within this constructor.
Following these guidelines allows EF to discover and use your configuration automatically by both tooling that needs to access your model and when your application is run.
Example
A class derived from DbConfiguration might look like this:
using System.Data.Entity; 
using System.Data.Entity.Infrastructure; 
using System.Data.Entity.SqlServer; 
namespace MyNamespace 
    public class MyConfiguration : DbConfiguration 
    { 
        public MyConfiguration() 
        { 
            SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy()); 
            SetDefaultConnectionFactory(new LocalDbConnectionFactory("v11.0")); 
        } 
    } 
}
This class sets up EF to use the SQL Azure execution strategy - to automatically retry failed database operations - and to use Local DB for databases that are created by convention from Code First.
Moving DbConfiguration
There are cases where it is not possible to place your DbConfiguration class in the same assembly as your DbContext class. For example, you may have two DbContext classes each in different assemblies. There are two options for handling this.
The first option is to use the config file to specify the DbConfiguration instance to use. To do this, set the codeConfigurationType attribute of the entityFramework section. For example:
<entityFramework codeConfigurationType="MyNamespace.MyDbConfiguration, MyAssembly"> 
    ...Your EF config... 
</entityFramework>
The value of codeConfigurationType must be the assembly and namespace qualified name of your DbConfiguration class.
The second option is to place DbConfigurationTypeAttribute on your context class. For example:
[DbConfigurationType(typeof(MyDbConfiguration))] 
public class MyContextContext : DbContext 
}
The value passed to the attribute can either be your DbConfiguration type - as shown above - or the assembly and namespace qualified type name string. For example:
[DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssembly")] 
public class MyContextContext : DbContext 
}
Setting DbConfiguration explicitly
There are some situations where configuration may be needed before any DbContext type has been used. Examples of this include:
Using DbModelBuilder to build a model without a context
Using some other framework/utility code that utilizes a DbContext where that context is used before your application context is used
In such situations EF is unable to discover the configuration automatically and you must instead do one of the following:
Set the DbConfiguration type in the config file, as described in the Moving DbConfiguration section above
Call the static DbConfiguration.SetConfiguration method during application startup
Overriding DbConfiguration
There are some situations where you need to override the configuration set in the DbConfiguration. This is not typically done by application developers but rather by thrid party providers and plug-ins that cannot use a derived DbConfiguration class.
For this, EntityFramework allows an event handler to be registered that can modify existing configuration just before it is locked down.  It also provides a sugar method specifically for replacing any service returned by the EF service locator. This is how it is intended to be used:
At app startup (before EF is used) the plug-in or provider should register the event handler method for this event. (Note that this must happen before the application uses EF.)
The event handler makes a call to ReplaceService for every service that needs to be replaced.
For example, to repalce IDbConnectionFactory and DbProviderService you would register a handler something like this:
DbConfiguration.Loaded += (_, a) => 
   { 
       a.ReplaceService<DbProviderServices>((s, k) => new MyProviderServices(s)); 
       a.ReplaceService<IDbConnectionFactory>((s, k) => new MyConnectionFactory(s)); 
   };
In the code above MyProviderServices and MyConnectionFactory represent your implementations of the service.
You can also add additional dependency handlers to get the same effect.
Note that you could also wrap DbProviderFactory in this way, but doing so will only effect EF and not uses of the DbProviderFactory outside of EF. For this reason you’ll probably want to continue to wrap DbProviderFactory as you have before.
You should also keep in mind the services that you run externally to your application - e.g. running migrations from Package Manager console. When you run migrate from the console it will attempt to find your DbConfiguration. However, whether or not it will get the wrapped service depends on where the event handler it registered. If it is registered as part of the construction of your DbConfiguration then the code should execute and the service should get wrapped. Usually this won’t be the case and this means that tooling won’t get the wrapped service
Handling of Transaction Commit Failures (EF6.1 Onwards)
As part of 6.1 we are introducing a new connection resiliency feature for EF: the ability to detect and recover automatically when transient connection failures affect the acknowledgement of transaction commits. The full details of the scenario are best described in the blog post SQL Database Connectivity and the Idempotency Issue.  In summary, the scenario is that when an exception is raised during a transaction commit there are two possible causes:
The transaction commit failed on the server
The transaction commit succeeded on the server but a connectivity issue prevented the success notification from reaching the client
When the first situation happens the application or the user can retry the operation, but when the second situation occurs retries should be avoided and the application could recover automatically. The challenge is that without the ability to detect what was the actual reason an exception was reported during commit, the application cannot choose the right course of action. The new feature allows EF to double-check with the database if the transaction succeeded and take the right course of action transparently.
Using the feature
In order to enable the feature you need include a call to SetTransactionHandler in the constructor of your DbConfiguration. If you are unfamiliar with DbConfiguration, see Code Based Configuration. This feature can be used in combination with the automatic retries we introduced in EF6, which help in the situation in which the transaction actually failed to commit on the server due to a transient failure:
using System.Data.Entity; 
using System.Data.Entity.Infrastructure; 
using System.Data.Entity.SqlServer; 
public class MyConfiguration : DbConfiguration  
  public MyConfiguration()  
  {  
    SetTransactionHandler(SqlProviderServices.ProviderInvariantName, () => new CommitFailureHandler());  
    SetExecutionStrategy(SqlProviderServices.ProviderInvariantName, () => new SqlAzureExecutionStrategy());  
  }  
}
How transactions are tracked
When the feature is enabled, EF will automatically add a new table to the database called __Transactions. A new row is inserted in this table every time a transaction is created by EF and that row is checked for existence if a transaction failure occurs during commit.
Although EF will do a best effort to prune rows from the table when they aren’t needed anymore, the table can grow if the application exits prematurely and for that reason you may need to purge the table manually in some cases.

Code First DataAnnotations

Julie Lerman
Published: April 2011
Download the code for this article

Entity Framework Code First modeling workflow allows you to use your own domain classes to represent the model which EF relies on to perform querying, change tracking and updating functions. Code first leverages a programming pattern referred to as convention over configuration. What this means is that code first will assume that your classes follow the conventions of the schema that EF uses for a conceptual model. In that case, EF will be able to work out the details it needs to do its job. However, if your classes do not follow those conventions, you have the ability to add configurations to your classes to provide EF with the information it needs.
Code first gives you two ways to add these configurations to your classes. One is using simple attributes called DataAnnotations and the other is using code first’s Fluent API, which provides you with a way to describe configurations imperatively, in code.
This article will focus on using DataAnnotations (in the System.ComponentModel.DataAnnotations namespace) to configure your classes – highlighting the most commonly needed configurations. DataAnnotations are also understood by a number of .NET applications, such as ASP.NET MVC which allows these applications to leverage the same annotations for client-side validations.
I’ll demonstrate code first DataAnnotations with a simple pair of classes: Blog and Post.
public class Blog 
  { 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public string BloggerName { get; set;} 
    public virtual ICollection<Post> Posts { get; set; } 
  } 
  public class Post 
  { 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public DateTime DateCreated { get; set; } 
    public string Content { get; set; } 
    public int BlogId { get; set; } 
    public ICollection<Comment> Comments { get; set; } 
  }
You can read the whitepaper, Building an MVC 3 App with Code First and Entity Framework 4.1, which demonstrates using these classes with Entity Framework 4.1 Code First in an MVC 3 application. I’ll use the same application to demonstrate Data Annotations in action.
As they are, the Blog and Post classes conveniently follow code first convention and required no tweaks to help EF work with them. But you can also use the annotations to provide more information to EF (and to MVC 3) about the classes and the database that they map to.

Key

Entity Framework relies on every entity having a key value (aka EntityKey) that it uses for tracking entities. One of the conventions that code first depends on is how it implies which property is the key in each of the code first classes. That convention is to look for a property named “Id” or one that combines the class name and “Id”, such as “BlogId”. In addition to EF’s use of the EntityKey, the property will map to a primary key column in the database.
The Blog and Post classes both follow this convention. But what if they didn’t? What if Blog used the name PrimaryTrackingKey instead or even foo? If code first does not find a property that matches this convention it will throw an exception because of Entity Framework’s requirement that you must have a key property. You can use the key annotation to specify which property is to be used as the EntityKey.
public class Blog 
  { 
    [Key] 
    public int PrimaryTrackingKey { get; set; } 
    public string Title { get; set; } 
    public string BloggerName { get; set;} 
    public virtual ICollection<Post> Posts { get; set; } 
  }
If you are using code first’s database generation feature, the Blog table will have a primary key column named PrimaryTrackingKey which is also defined as an IdentityKey by default.

Required

The Required annotation tells EF that a particular property is required.
Adding Required to the Title property will force EF and MVC to ensure that the property has data in it.
[Required] 
public string Title { get; set; }
With no additional no code or markup changes in the application, my existing MVC application will perform client side validation, even dynamically building a message using the property and annotation names.

Figure 1
With MVC’s client-side validation feature turned off, you will get the same response, except that it will be a result of server-side validation. Entity Framework will perform the validation on the Required annotation and return the error to MVC which will display the message.
The Required attribute will also affect the generated database by making the mapped property non-nullable. Notice that the Title field has changed to “not null”.

MaxLength and MinLength

The MaxLength and MinLength attributes allow you to specify additional property validations, just as you did with Required.
Here is the BloggerName with length requirements. The example also demonstrates how to combine attributes.
[MaxLength(10),MinLength(5)] 
      public string BloggerName { get; set; }
The MaxLength annotation will impact the database by setting the property’s length to 10. Prior to that, the default length was 128 as is the length of Title.
MVC 3 client-side annotation and EF 4.1 server-side annotation will both honor this validation, again dynamically building an error message: “The field BloggerName must be a string or array type with a maximum length of '10'.” That message is a little long. Many annotations let you specify an error message with the ErrorMessage attribute.
[MaxLength(10, ErrorMessage="BloggerName must be 10 characters or less"),MinLength(5)] 
public string BloggerName { get; set; }
You can also specify ErrorMessage in the Required annotation.
Figure 2

NotMapped

Code first convention dictates that every property is represented in the database. But this isn’t always the case in your applications. For example you might have a property in the Blog class that creates a code based on the Title and BloggerName fields. That property can be created dynamically and does not need to be stored. You can mark any properties that do not map to the database with the NotMapped annotation such as this BlogCode property.
[NotMapped] 
        public string BlogCode{ 
            get{ 
                return Title.Substring(01) + ":" + BloggerName.Substring(01); 
            } 
        }

ComplexType

It’s not uncommon to describe your domain entities across a set of classes and then layer those classes to describe a complete entity. For example, you may add a class called BlogDetails to your model.
public class BlogDetails 
    { 
        public DateTime? DateCreated { get; set; } 
        [MaxLength(250)] 
        public string Description { get; set; } 
    }
Notice that BlogDetails does not have any type of key property. In domain driven design, BlogDetails is referred to as a value object. Entity Framework refers to value objects as complex types.  Complex types cannot be tracked on their own.
However as a property in the Blog class, BlogDetails it will be tracked as part of a Blog object. In order for code first to recognize this, you must mark the BlogDetails class as a ComplexType.
[ComplexType] 
    public class BlogDetails 
    { 
        public DateTime? DateCreated { get; set; } 
        [MaxLength(250)] 
        public string Description { get; set; } 
    }
Now you can add a property in the Blog class to represent the BlogDetails for that blog.
    public BlogDetails BlogDetail { get; set; }
In the database, the Blog table will contain all of the properties of the blog include the properties contained in its BlogDetail property. By default, each one is preceded with the name of the complex type, BlogDetail, as you can see in Figure 3.

Figure 3: The Blogs database table containing columns that map to a complex type
Another interesting note is that although the DateCreated property was defined as a non-nullable DateTime in the class, the relevant database field is nullable. You must use the Required annotation if you wish to affect the database schema.

ConcurrencyCheck

The ConcurrencyCheck annotation allows you to flag one or more properties to be used for concurrency checking in the database when a user edits or deletes an entity. If you've been working with Entity Data Model, this aligns with setting a property's ConcurrencyMode to Fixed.
Let’s see how ConcurrencyCheck works by adding it to the BloggerName property.
[ConcurrencyCheck, 
 MaxLength(10, ErrorMessage="BloggerName must be 10 characters or less"), 
 MinLength(5)] 
public string BloggerName { get; set; }
Concurrency checking depends on having access to the original value of the property. If the context instance that originally queried for a blog stays in memory, it will retain knowledge of the original values of the blog along with its current values. But in a disconnected application, such as the MVC application being used, you’ll need to remind the context of that original value.
You can do that using this db.entry property method before calling SaveChanges. In the following Edit postback method of the sample MVC application, the UI has returned the original value of the blogger name in the originalName parameter. Then it is applied to the DbContext’s tracking entry by setting the Property’s OriginalValue as you can see in the line of code just before SaveChanges is called.
[HttpPost] 
        public ActionResult Edit(int id, string originalName, Blog blog) 
        { 
            try 
            { 
                db.Entry(blog).State = System.Data.EntityState.Modified; 
                db.Entry(blog).Property(b => b.BloggerName).OriginalValue = originalName; 
                db.SaveChanges(); 
                return RedirectToAction("Index"); 
            } 
            catch 
            { 
                return View(); 
            } 
        }
When SaveChanges is called, because of the ConcurrencyCheck annotation on the BloggerName field, the original value of that property will be used in the update. The command will attempt to locate the correct row by filtering not only on the key value but also on the original value of BloggerName.  Here are the critical parts of the UPDATE command sent to the database, where you can see the command will update the row that has a PrimaryTrackingKey is 1 and a BloggerName of “Julie” which was the original value when that blog was retrieved from the database.
where (([PrimaryTrackingKey] = @4) and ([BloggerName] = @5)) 
@4=1,@5=N'Julie'
If someone has changed the blogger name for that blog in the meantime, this update will fail and you’ll get a DbUpdateConcurrencyException that you'll need to handle.

TimeStamp

It's more common to use rowversion or timestamp fields for concurrency checking. But rather than using the ConcurrencyCheck annotation, you can use the more specific TimeStamp annotation as long as the type of the property is byte array. Code first will treat Timestamp properties the same as ConcurrencyCheck properties, but it will also ensure that the database field that code first generates is non-nullable. You can only have one timestamp property in a given class.
Adding the following property to the Blog class:
[Timestamp] 
        public Byte[] TimeStamp { get; set; }
results in code first creating a non-nullable timestamp column in the database table.

Table and Column

You can also use code first with an existing database. But it's not always the case that the names of the classes and properties in your domain match the names of the tables and columns in your database.
My class is named Blog and by convention, code first presumes this will map to a table named Blogs. If that's not the case you can specify the name of the table with the Table attribute. Here for example, the annotation is specifying that the table name is InternalBlogs.
[Table("InternalBlogs")] 
   public class Blog
You can also use the Table attribute when code first is creating the database for you if you simply want the table name to be different than the convention.
The Column annotation is a more adept in specifying the attributes of a mapped column. You can stipulate a name, data type or even the order in which a column appears in the table. Here is an example of the Column attribute.
[Column(“BlogDescription", TypeName="ntext")] 
   public String Description {get;set;}
Don’t confuse Column’s TypeName attribute with the DataType DataAnnotation. DataType is an annotation used for the UI and is ignored by code first.
Here is the table after it’s been regenerated. The table name has changed to InternalBlogs and Description column from the complex type is now BlogDescription. Because the name was specified in the annotation, code first will not use the convention of starting the column name with the name of the complex type.

DatabaseGenerated

An important database features is the ability to have computed properties. If you're mapping your code first classes to tables that contain computed properties, you don't want Entity Framework to try to update those columns. But you do want EF to return those values from the database after you've inserted or updated data. You can use the DatabaseGenerated annotation to flag those properties in your class along with the Computed enum. Other enums are None and Identity.
[DatabaseGenerated(DatabaseGenerationOption.Computed)] 
     public DateTime DateCreated { get; set; }
You can use database generated on byte or timestamp columns when code first is generating the database, otherwise you should only use this when pointing to existing databases because code first won't be able to determine the formula for the computed column.
You read above that by default, a key property will become an identity key in the database. That would be the same as setting DatabaseGenerated to DatabaseGenerationOption.Identity. If you do not want it to be an identity key, you can set the value to DatabaseGenerationOption.None.

Relationship Attributes: InverseProperty and ForeignKey

Code first convention will take care of the most common relationships in your model, but there are some cases where it needs help.
Changing the name of the key property in the Blog class created a problem with its relationship to Post. 
When generating the database, code first sees the BlogId property in the Post class and recognizes it, by the convention that it matches a class name plus “Id”, as a foreign key to the Blog class. But there is no BlogId property in the blog class. The solution for this is to create a navigation property in the Post and use the Foreign DataAnnotation to help code first understand how to build the relationship between the two classes —using the Post.BlogId property — as well as how to specify constraints in the database.
public class Post 
    { 
        public int Id { get; set; } 
        public string Title { get; set; } 
        public DateTime DateCreated { get; set; } 
        public string Content { get; set; } 
        public int BlogId { get; set; } 
        [ForeignKey("BlogId")] 
        public Blog Blog { get; set; } 
        public ICollection<Comment> Comments { get; set; } 
    }
Figure 4 shows the constraint in the database that creates a relationship between InternalBlogs.PrimaryTrackingKey and Posts.BlogId. 

Figure 4
The InverseProperty is used when you have multiple relationships between classes.
In the Post class, you may want to keep track of who wrote a blog post as well as who edited it. Here are two new navigation properties for the Post class.
public Person CreatedBy { get; set; } 
        public Person UpdatedBy { get; set; }
You’ll also need to add in the Person class referenced by these properties. The Person class has navigation properties back to the Post, one for all of the posts written by the person and one for all of the posts updated by that person.
public class Person 
    { 
        public int Id { get; set; } 
        public string Name { get; set; } 
        public List<Post> PostsWritten { get; set; } 
        public List<Post> PostsUpdated { get; set; } 
    }
Code first is not able to match up the properties in the two classes on its own. The database table for Posts should have one foreign key for the CreatedBy person and one for the UpdatedBy person but code first will create four will foreign key properties: Person_Id, Person_Id1, CreatedBy_Id and UpdatedBy_Id.
To fix these problems, you can use the InverseProperty annotation to specify the alignment of the properties.
[InverseProperty("CreatedBy")] 
        public List<Post> PostsWritten { get; set; } 
        [InverseProperty("UpdatedBy")] 
        public List<Post> PostsUpdated { get; set; }
Because the PostsWritten property in Person knows that this refers to the Post type, it will build the relationship to Post.CreatedBy. Similarly, PostsUpdated will be connected to Post.UpdatedBy. And code first will not create the extra foreign keys.

Summary

DataAnnotations not only let you describe client and server side validation in your code first classes, but they also allow you to enhance and even correct the assumptions that code first will make about your classes based on its conventions. With DataAnnotations you can not only drive database schema generation, but you can also map your code first classes to a pre-existing database.
While they are very flexible, keep in mind that DataAnnotations provide only the most commonly needed configuration changes you can make on your code first classes. To configure your classes for some of the edge cases, you should look to the alternate configuration mechanism, code first’s Fluent API .

About the Author

Julie Lerman is a Microsoft MVP, .NET mentor and consultant who lives in the hills of Vermont. You can find her presenting on data access and other Microsoft .NET topics at user groups and conferences around the world. Julie blogs at  thedatafarm.com/blog and is the author of the highly acclaimed book, “Programming Entity Framework” (O’Reilly Media, 2009). Follow her on Twitter.com:

No comments:

Post a Comment