* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Entity Framework
Survey
Document related concepts
Microsoft SQL Server wikipedia , lookup
Oracle Database wikipedia , lookup
Open Database Connectivity wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Navitaire Inc v Easyjet Airline Co. and BulletProof Technologies, Inc. wikipedia , lookup
Functional Database Model wikipedia , lookup
Extensible Storage Engine wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Ingres (database) wikipedia , lookup
Concurrency control wikipedia , lookup
Versant Object Database wikipedia , lookup
Relational model wikipedia , lookup
Clusterpoint wikipedia , lookup
Transcript
Entity Framework CODE FIRST – PRACTICAL WALKTHROUGH 22.05.2017 1 Entity Framework Code First– practical walkthrough This presentation will be explain how Entity Framework Code First can be used Entity Framework Code First will be called EF Code First EF Code First is used as an object relational mapper (ORM), where the representation of a database is described through a set of classes, called the POCO classes EF Code First uses conventions to describe different parts of a database, such as tables, keys, constraints, relations to other tables and their cardinality and so on Different practical examples will be presented to show how to do different techniques 22.05.2017 2 How to get started with EF Code First A database is of course required for EF Code First EF Code First will be able to create a database to be used in a development environment For the database in the production environment, it is recommended to use database scripts to create and update the database. It is possible to generate update scripts for any revision or migration of the database. EF Code First migrations can update the database to a target revision in development environments To get started with EF Code First, check that Entity Framework is installed. The current version at the time of March 2014 is Entity Framework 6.1.0. Use the package manager console to install EF if not installed yet. The command to install the EF Nuget package is: install-package EntityFramework 22.05.2017 3 Starting using EF Code First First off, a context type must be created. This is a class that will be the primary class to interact with the database. To create such a class, create a public class that inherits from the class DbContext in the System.Data.Entity namespace After a class is added, enable EF Code Migrations Type the following command into the package manager console: Enable-Migrations 22.05.2017 4 Example of a db context class The following simple code is an example of a simple db context class using System.Data.Entity; namespace ConsoleApplication1 { public class DemoDbContext : DbContext { public DemoDbContext() { } public DbSet<PasSystem> PasSystems { get; set; } } } Notice that tables are defined as instances of the generic class DbSet, where the type argument specifies the POCO class that will represent the table with the same name. 22.05.2017 5 Using a dbcontext class The syntax to query a EF Code First dbcontext class is Linq to Entities, also used in model based Entity Framework To query the database, the following code shows a simple example: using (var context = new SchoolEntities()) { context.Departments.Add(new Department { Name = «Development department", StartDate = new DateTime(2004, 1, 1) }); context.SaveChanges(); } 22.05.2017 6 Adding migrations Migrations are versions of the database. The database can be updated a target migration or previous migration. It is possible to move in any direction of these migrations and also create update scripts for changing the database to a revision. Obviously, in production, extra care should be taken to avoid data loss. Also, most DBAs will require database update scripts. EF Code First migrations can generate update scripts to target any revision. In a development environment, updating a database to a target migration can be done via the package manager console, as long as the running user has got the permission to do so To add a migration, use the package manager console and type: Add-Migration MyMigration This will add a migration as a partial class in the Migrations folder of the current solution. The migration is the transform from the current state of the database to the target state, which is changed through changing the POCO classes defining the database. The POCO classes that make up the database is listed in the DbContext class directly or indirectly by one of these classes referring to another POCO class through a navigation property. 22.05.2017 7 Updating to a revision of the database To update to a target revision of the database, type the following command in the package manager console: Update-Database or to watch the SQL being run: Update-Database -verbose To generate a script instead to manually update the database, type the following command in the package manager console: Update-Database –Script or for example: Update-Database –SourceMigration SomeMigration –TargetMigration SomeOtherMigration This will generate a script for updating the database to the pending migration. To update the database to a target migration, type the following command in the package manager console Update-Database –targetmigration MyMigration To update to before the first migration: Update-Database –targetmigration:$InitialDatabase 22.05.2017 8 Conventions of EF Code First EF Code First is based on conventions to modify and interact with a target database These conventions must be followed to define the structure of the database (schema) One convention is that columns are defined as public automatic properties The primary key can be defined by defining a property called the name of the POCO class and suffixing it with «Id». E.g. the table Patient can look like the following, where the PatientId column will be the primary key (the primary key can also be named just Id or ID): public class Patient { public int PatientId { get; set; } public string PatientName { get; set; } public int Age { get; set; } } 22.05.2017 9 Using attributes to specify keys and constraints It is possible to use attributes on properties to specify constraints and keys To specify a primary key, the attribute [Key] can be used on the property. This is more specific and allows setting a primary key to another name than «tableId». To specify a foreign key, the attribute [ForeignKey] can be used. Note that the foreign key also must follow the naming convention «tableId» to identify the table this foreign key specifies a relation to the current POCO class or table To specify a constraint such as length of a string in the POCO class, the [MaxLength(n)] attribute can be used. To specify a length of ten characters for a string, use [MaxLength(10)] This will then be mapped to a nvarchar(10) column In addition, the fluent API can be used to specify constraints, keys and relations. For example: modelBuilder.Entity<Department>().Property(d => d.Name).HasMaxLength(50); One should consider not mixing styles here and consistently use attributes, fluent API or both. Note that attributes are not able to describe all aspects of a database, so understanding the fluent API will be required 22.05.2017 10 Database initializers When initializing the database, it is possible to set a database intializer somewhere in the startup code of the application with the static method: Database.SetInitializer – for example: Database.SetInitializer(new MigrateDatabaseToLatestVersion<SomeDbContext,Configuration>()); The call is usually done once the application starts. It is possible to create a custom database initializer by implementing the interface IDatabaseInitializer Other available initializers are: DropCreateDatabaseIfModelChanges, DropCreateDatabaseAlways, CreateDatabaseIfNotExists Also note that automatic migrations can be turned on or off by setting the following protected property to false in the Configuration class in the Migrations folder: AutomaticMigrationsEnabled = false; Usually, it is better to manually update the database through the package manager console in development environments, while updating the database in the production environment by manually running update scripts. Most DBAs will require this, as the code running the updating of migrations must have special privileges on the database if an update will be performed through code of the database. There setting AutomaticMigrationsEnabled to false gives manual control of when the database should be migrated. 22.05.2017 11 Reverse engineering a database Reverse engineering a database is possible To do this, install the extension Entity Framework Power Tools Beta 4 To start reverse engineering, right click on a project and choose Entity Framework> Reverse Engineer Code First 22.05.2017 12 Reverse engineering contd. Before the reverse engineering can commence, the connection to the database must be set up. The reverse engineering will generate the POCO classes and additional classes such as the db context and define relationships between classes using mapping classes which uses the fluent API of EF Code First Using reverse engineering, it is possible to get a generated EF Code First db context to an existing database that supports migrations. This allows quick start-up of starting with EF Code First and and moving from another ORM, such as Entity Framework using a model (EDMX file) 22.05.2017 13 SQL Server Data Tools (SSDT) Another great add-on for Visual Studio is SSDT – SQL Server Data Tools. It is available to different versions of Visual Studio, such as VS 2012 and VS 2013 The addon makes it easy to inspect tables of SQL Server databases and see the schema details of the tables Effectively this gives the developer much of the functionality of SQL Management Studio inside Visual Studio Download page is here: http://msdn.microsoft.com/en-us/data/hh297027 22.05.2017 14 Database creation and target db When creating a database, EF Code First will default to create a new database on the local SQLEXPRESS instance (.\SQLEXPRESS) If not SQLEXPRESS is installed, (LocalDb)\v11.0 is used (installed with VS2012 and VS2013) It is possible to use another database, by specifiying this in a connection string in the application configuration file and specify the connection string key in the constructor of the dbcontext class. Example. Note correspondence between name attribute in the connection string and Name= in the constructor: <add name="CodeFirstSimpleDemoContextContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=CodeFirst Simple.DemoContext;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" /> public CodeFirstSimpleDemoContextContext() : base("Name=CodeFirstSimpleDemoContextContext"){ .. } 22.05.2017 15 Navigation properties in POCO classes To add navigation properties to the POCO classes, add a property with the type of the other table. To specify navigation property to a single entity in the other table specify a property with this type. To specify a navigation property to a collection of entities in the other table, specify a property of type ICollection of the type of the other table. To support lazy loading, specify the virtual keywordof the property. The lazy loading will result in quicker execution in different scenarios. The loading of entities are postponed until they are referenced directly in the code. An example relationship between the two tables Course and Department is shown on the next slide. One department can have many courses, so the relationship is 1:n. This means that the Course table will have a foreign key to the Department table. 22.05.2017 16 EF Code First 1:n relationship The following POCO classes define a 1:n relationship between tables Department and Course. One department can have many courses, but a course has only one department. Because virtual keyword is used, these navigation properties have lazy loading. Also note that ICollection is used here. DEPARTMENT using System; using System.Collections.Generic; namespace CodeFirstSimple { public class Department { public Department() { this.Courses = new HashSet<Course>(); } public int DepartmentId { get; set; } public string Name { get; set; } public decimal Budget { get; set; } public DateTime StartDate { get; set; } public int? Administrator { get; set; } public virtual ICollection<Course> Courses { get; set; } COURSE namespace CodeFirstSimple { public class Course { public int CourseId { get; set; } public string Title { get; set; } public int Credits { get; set; } public int DepartmentId { get; set; } public virtual Department Department { get; set; } } } } } 22.05.2017 17 EF Code First 1:0..1 relationship Also known as optional 1:1 relationship. Example below. Table Instructor and table Address has got a 1:0..1 relationship. One Instructor may have an address. The relationship is mapped as a nullable foreign key that points to the Address table. public public public public public public } class Address { string AdressId { get; set; } string PostalPlace { get; set; } int ZipCode { get; set; } string StreetAddress { get; set; } virtual Instructor Instructor { get; set; } To add an optional foreign key using fluent API, called InstructorAddressId in the Instructor table, the following syntax is used: modelBuilder.Entity<Instructor>() .HasOptional<Address>(i => i.Address) .WithOptionalDependent(a => a.Instructor) .Map(a => a.MapKey("InstructorAddressId")); 22.05.2017 public class Instructor { public Instructor() { this.Courses = new List<Course>(); } // Primary key public int InstructorID { get; set; } public string LastName { get; set; } public string FirstName { get; set; } public System.DateTime HireDate { get; set; } // Navigation properties public virtual Address Address { get; set; } public virtual ICollection<Course> Courses { get; private set ; } } 18 EF Code First m:n relationship Also known as many-to-many relationships Example below, with Tags and Posts, defining a m:n relationship. public class Post { public int Id { get; set; } public string Title { get; set; } public DateTime DateCreated { get; set; } public DateTime LastUpdate { get; set; } public string Content { get; set; } public int FKBlogId { get; set; } public Blog Blog { get; set; } public ICollection<Tag> Tags { get; set; } } public class Tag { public int TagId { get; set; } public string Name { get; set; } public ICollection<Post> Posts { get; set; } } Actually, EF Code First will automatically create a table to express this relationship called TagPosts. EF Code First will create a table with the primary key(s) from both tables in the relationship and call each column in this table for: tablename + «_» + primary key column name. The resulting table is shown above in the screen capture. 22.05.2017 19 EF Code First m:n relationships contd. To create link tables in m:n relationships between two tables, it is possible to define navigation properties in the two entities that point to eachother (and is of type ICollection) It is also possible with the fluent API to have a more specific naming of the link table. Example below: modelBuilder.Entity<Post>().HasMany(p => p.Tags).WithMany(t => t.Posts) .Map( m => { m.ToTable("PostTags"); m.MapLeftKey("PostId"); m.MapRightKey("TagId"); }); In the example code above, the name of the link table is called PostTags and the Map method is used, specifying the key names of this table. Make note that the parameters in the MapLeftKey is the primary key names of the left entity (Post) and in the MapRightKey is the primary key names of the right entity (Tags). It is possible to have several primary key columns and these two methods takes a params string array. 22.05.2017 20 Entity splitting It is sometimes desired to split an entity into two or more tables, known as entity splitting In the example below, the entity Department is split into two tables Department and DepartmentDetails. modelBuilder.Entity<Department>() .Map(m => { m.Properties(d => new { d.DepartmentID, d.Name }); m.ToTable("Department"); }) .Map(m => { m.Properties(d => new { d.DepartmentID, d.Name, d.Administrator, d.StartDate }); m.ToTable("DepartmentDetails"); }); Another strategy is of course to create POCO classes for each table as usual. This can also be considered a cleaner, more consistent strategy. 22.05.2017 21 Specifying identity for numeric primary key Numeric primary keys (integer based) of tables will automatically be created with identity increment set to (1,1) (seed and increment) in EF Code First To specifically set database generation options the following example shows how this can be specified in the fluent API: modelBuilder.Entity<Department>().Property(d => d.DepartmentID) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); In addition, it is possible to set the HasDataBaseGeneratedOption to Computed or None. 22.05.2017 22 Specifying a multi-column primary key It is possible to create a multi-column primary key for a table by using the fluent API. The following example shows how to create a two-column primary key in the Department table: modelBuilder.Entity<Department>() .HasKey(d => new { d.DepartmentID, d.Name }); 22.05.2017 23 Creating indexes with EF Code First Creating indexes with EF Code First can be done with different technique. One technique is to add an empty migration and manually add in the code for creating or dropping the index in the Up and Down method of the migration. Example below. Creating a non-unique index on the ZipCode column in the Address table / entity can be done by first running: AddMigration CreateAddressZipCodeIndex (arbitrary name): namespace DepartmentDemo.Migrations { using System; using System.Data.Entity.Migrations; public partial class CreateAddressZipCodeIndex : DbMigration { public override void Up(){ CreateIndex("Address", "ZipCode", false, "IX_Address_ZipCode"); } public override void Down(){ DropIndex("Address", "IX_Address_ZipCode"); } } } The code above shows how to create and drop an index. The first argument is the table name of which the index belongs, and the next argument is either a string or an array of strings of the column(s) to create the index on. The next argument specifies if the index is unique or not and the last parameter is the name of the index. The Down method drops the index and the Up method creates the index. Both methods must be implemented so that migrations up and down is possible. 22.05.2017 24 EF Code First vs Entity Model-based: Pros and Cons The following pros and cons are author based and should be considered as suggestive guidelines and nothing more. Pros EF Code First lacks a model file and therefore scales better when for larger, real-world scenarios. A large model (.edmx file) becomes unwieldy and hard to control when the amount of tables the model describes grow. Also changing branches with different migrations is also hard to control, since this is done manually. The model file also contains a lot of metadata. The POCO classes of EF Code First are however easier to scale. Since EF Code First is code based, the programmer is put more in the front seat of controlling the database. The definition of the database is much clearer than in the model based approach. Instead of generating classes from a model, the developer writes entity classes manually and can also control how migrations are done between versions of the database, as development progresses. 22.05.2017 25 EF Code First vs Entity Model-based: Pros and cons contd. Cons A steeper learning curve is associated with EF Code First than model based approaches In the model based approach, the developer will use for example SQL Management Studio and design the database in a database diagram, generate change scripts, commit the change script, open up the model file and update the model file towards the database. In EF Code First, the programmer must manually create POCO classes for the entities. Relationships between the tables must be in most cases be expressed using the fluent API of EF Code First. In other words, EF Code First means that the programmers must also learn how to create entity tables and other aspects of a database manually. Sometimes, moving between migrations becomes challenging because of conflicting changes. Also the programmer’s intent is not always matched. Requirements for a database changes over time. Sometimes, applying changes or migrations to a database becomes hard, because there are conflicting changes between the existing database structure and the desired structure. Also, the intent of the programmer is sometimes not expressed correctly in EF Code First because of misinterpretations. Care must be taken so that the desired change matches the actual change to the database. It is recommended to turn off automatic migrations being applied and generate database change scripts so this process can be controlled. 22.05.2017 26 Summary EF Code First is a modern approach to creating a data layer object relational mapping between data layer classes and a physical database. EF Code First supports migrations (versions) of the database and moving up or down between these. Care should be taken to avoid data loss, therefore chronologically moving up to the next migration is suggested. EF Code First can also generate change scripts and in code it is possible to create entities and specify relations between entities / tables. Check out these web pages for more information about EF Code First: Data Developer Center > Learn > Entity Framework > Get Started > Code First to a New Database http://msdn.microsoft.com/en-us/data/jj193542.aspx EF Code First End To Video (75 mins): https://www.youtube.com/watch?v=l3WzYZsN0gU 22.05.2017 27