[EF] How to manually set the Migration job of Code First in Entity Framework, entitymigration

Source: Internet
Author: User

[EF] How to manually set the Migration job of Code First in Entity Framework, entitymigration

The Entity Framework (EF) has developed to the present, and the version has entered 6.1.0. It has been six months since I wrote the article "build an EF database in Code First mode in VS2013. If you started using EF Code First like me at that time, you should have a basic understanding of EF. In my personal experience, EF is easy to use, but if you have been using AutomaticMigrations to maintain your database, you may encounter some trouble. In a normal operating environment, the format of the database cannot be changed forever. When we have started writing data, the situation will become more complex, it forces us to explore more appropriate and flexible practices.
Here, I will introduce how to manually do the Migrations by discarding AutomaticMigrations. I don't think I can explain it in simple words in a simple and easy way. I can only take you step by step to do it myself, so that you can understand the secrets in your workshop.

Step 1

Please use VS2013 to create a project (I personally use the Console project ), install the latest Entity Framework, customize the Connection String, and set up the category of the data according to the method described in "create EF database with Code First in VS2013, enable and operate the Package Manager Console window.

If you have not subscribed to your database, you can use the following sample categories. I will always use this category in this article.

using System;using System.Collections.Generic;using System.Data.Entity;using System.ComponentModel.DataAnnotations;using System.ComponentModel.DataAnnotations.Schema;namespace EfDemo.Model{    public class AddressInfo    {        [Key]        public int AddressId { get; set; }        public string Address { get; set; }    }    public class TaiwanAddress: DbContext    {        public TaiwanAddress() : base("TaiwanAddress") { }        public DbSet<AddressInfo> Addresses { get; set; }    }}

At the same time, your App. config should look like the following:

<? Xml version = "1.0" encoding = "UTF-8"?> <Configuration> <configSections> <! -- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <Section name = "entityFramework" type = "System. data. entity. internal. configFile. entityFrameworkSection, EntityFramework, Version = 6.0.0.0, Culture = neutral, publicKeyToken = b77a5c561934e089 "requirePermission =" false "/> </configSections> <startup> <supportedRuntime version =" v4.0 "sku = ". NETFramework, Version = v4.5 "/> </startup> <connectionStrings> <add name =" TaiwanAddress "connectionString =" Data Source = your computer name \ SQLEXPRESS; initial Catalog = TaiwanAddress; Persist Security Info = True; User ID = your secret; Password = Your Secret "providerName =" System. data. sqlClient "/> </connectionStrings> <entityFramework> <defaultConnectionFactory type =" System. data. entity. infrastructure. sqlConnectionFactory, EntityFramework "/> <providers> <provider invariantName =" System. data. sqlClient "type =" System. data. entity. sqlServer. sqlProviderServices, EntityFramework. sqlServer "/> </providers> </entityFramework> </configuration>

Step 2

Locate the kit Manager Console (view, other windows, Kit Manager Console; versions other than VS2013 may not be here) and execute the Enable-Migrations command. If you have multiple projects in your solution, note that you must select this project from the "Default project" drop-down menu above.

 

For example, if you forget the correct spelling of the command, you can enter only the first few characters and press the <TAB> key. A Prompt window appears asking you to select the correct command.

After executing the Enable-Migrations command, you may see an error message saying that the Configuration type under Migrations cannot be found in the project. This is an incorrect command, so ignore it. Make sure that the Migrations folder and other Configuration. cs files are added to your project:

 

Step 3

Run the Add-Migration CreateDb command on the console:

 

As shown in, we can see a yellow description, which means, the Add-Migration CreateDb command stores the current Code First Model in the project as CreateDb (this name is customized. We recommend that you use a name that is easy to remember) snapshot. This Snapshot is used to record the modification history of the data model in your program so far, it will be used as the basis for the next Migrations comparison. However, if you modified your data model later but want to package it into the snapshot of CreateDb, you only need to re-Execute Add-Migration CreateDb.

I re-explain the above text in plain vernacular. If you want to drive your car to check whether there is a gas station near your home, you can first open a block and remember this process and call it a Run1 snapshot ). Then open a block to the left and remember this process as a Run2 snapshot ). And so on. By adding up the preceding Run operations, you will know your driving path and how to drive to the gas station next time.

However, when you open Run2 (a block to the left), you suddenly feel that you should include it in Run1 (a block to the Front) without the need to mark a Run2, then you can redefine the meaning of run1 ).

After the script is executed, an object named xxxx_CreateDb.cs is automatically enabled:

namespace EfDemo.Migrations{    using System;    using System.Data.Entity.Migrations;        public partial class CreateDb : DbMigration    {        public override void Up()        {            CreateTable(                "dbo.AddressInfoes",                c => new                    {                        AddressId = c.Int(nullable: false, identity: true),                        Address = c.String(),                    })                .PrimaryKey(t => t.AddressId);                    }                public override void Down()        {            DropTable("dbo.AddressInfoes");        }    }}

This file will be executed later when we execute Update-Database. The Up () and Down () methods in the program are relative. Basically, the Up () method is the job to be executed on the database, and the Down () method is Up () method. So in the future, if you want to Rollback the Migration, EF will execute the Down () method.

If you have any opinions on the content of the Up () or Down () method, you can also manually modify its program. For example, if you do not like EF to change your table name to AddressInfoes (ssinfo's ssinfo type), you can change it back to dbo. AddressInfo. However, you can't just change the Up () method. You also need to remember to change the Down () method at the same time.

However, we recommend that you do not modify the Up () and Down () Methods automatically generated by EF at this time. After all, we are just doing exercises here. Maybe you can do this when you are more familiar with EF. At the same time, we can use the attribute [Table ("AddressInfo")] to specify the name of the data Table (see the description in "create EF database in Code First mode in VS2013 ), therefore, the necessity to manually change the content of this program is very low. Do not modify automatically generated programs as much as possible. This is one of the important rules to prevent staying.

Step 4

Now let's look back at the Configuration. cs program created in Step 2. If we start the AutomaticMigration instead of manually performing the Migration, we can see that the AutomaticMigrationsEnabled is set to true rather than false in this Configuration construction.

But what is the Seed () method? According to its original annotation "This method will be called after migrating to the latest version", literally This Seed () the method will be called when we use migrate to the latest version. In fact, if we have set Migration (that is, the "CreateDb" snapshot created in the previous step ), when we execute the Update-Database command, EF will automatically call and execute this Seed () method.

Modify the file as follows:

Namespace EfDemo. migrations {using System; using System. data. entity; using System. data. entity. migrations; using System. linq; internal sealed class Configuration: DbMigrationsConfiguration <efdemo. addressdata> {public Configuration () {AutomaticMigrationsEnabled = false;} protected override void Seed (EfDemo. addressData context) {context. addresses. addOrUpdate (p => p. address, new Model. addressInfo {Address = "1 "}, new Model. addressInfo {Address =" 2 "});}}}

Here, I have rewritten the Seed () method to write two pieces of data into it. Here, AddOrUpdate () is an extension method, which has two types of multi-load. If you delete or annotate the p => p. Address Command, this is another syntax for multiple loads. However, if you use the preceding example (that is, retain p => p. Address), the two pieces of data will be written only once. If you delete or annotate p => p. Address in this line, the two pieces of data may be written into the database later.

Configuration. cs is automatically generated by EF, but it will not be generated again and again. Therefore, it is safe to modify it. Besides, the Seed () method was originally used for developers to modify.

Execute the Update-Database command. You will find that both the database and the data table have been created, and the above two pieces of data have been written.

The Seed () method is called every time you execute the Update-Database command. So you can try to add another "3 Kaida da Avenue" and execute the Update-Database command again, so there will be more in the Database. In other words, you can add data to the database in the same way.

In other words, you may have to think about when you will use the Seed () method to insert data into the database? In general, applying EF in a program is definitely not intended for inserting data using the Seed () method. However, we certainly want to add some fixed and difficult-to-change materials when the database is created, such as the address of our company or some test materials. Therefore, the Seed () method is indeed a great helper for developers.

Now, check your database and you will find that EF will create a "_ MigrationHistory" data table and write a record in it. Its MigrationId is the name of the. cs File Created by EF in the Migration folder.

Since the database already has information, we can read it from the program:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using EfDemo.Model;namespace EfDemo{    class Program    {        static void Main(string[] args)        {            using (var db = new TaiwanAddress())            {                foreach (AddressInfo info in db.Addresses)                {                    Console.WriteLine(info.Address);                }            }            Console.ReadKey();        }    }}

Press F5 to run the application and read the data from the database. However, the method of reading and writing databases via EF is not the focus of this article, so I will not focus much on it here.

Step 5

If your project is really simple, you only need to practice step 4 to make you happy. Unfortunately, it is difficult to find the dream situation in reality. So let's continue!

Add a field to your category, for example, DateCreated column:

public class AddressInfo{    [Key]    public int AddressId { get; set; }    public string Address { get; set; }    public DateTime DateCreated { get; set; }}

Remain unchanged elsewhere.

However, when you press F5 to run the application again, the following error occurs:

"The model backing the 'taiwanaddress' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink? LinkId = 238269 )."

It means that EF will issue an InvalidOperationException because your data category is already different from the version in the database. Therefore, from another perspective, whenever you see this message, you should know that your data category and database structure are inconsistent.

Therefore, whenever you change your data type, you must perform the Add-Migration operation again. Here, execute the Add-Migration AddDateCreated command and then issue the Update-Database command.

Sure enough, the database was updated smoothly. However, you will also find a row of red characters: "An error occurred while updating the entries. See the inner exception for details ."

This may be an issue where EF is not enough to think about. In fact, this problem occurs because we have added several starting materials to the Seed () method in Configuration. cs. Because the value of the DateCreated column is not null, an error occurs. However, if you carefully read the AddressInfoes content in the database, you will find that each DateCreated column has an initial value. In this case, this "error" message is not an "error", but a "warning" message. The program should indeed issue an Exception, but EF has automatically taken remedial measures.

Of course, it may also be the rescue measures used by My SQL Express own hacker, so the "error" message sent by it may also be correct.

In any case, if we add a not null column in the data category, but forget to make necessary modifications while writing data to the database, this is indeed our own mistake! We cannot take any action because EF or the database has taken the initiative to remedy the problem. Modify the Seed () method as follows:

Protected override void Seed (EfDemo. model. taiwanAddress context) {context. addresses. addOrUpdate (p => p. address, new Model. addressInfo {Address = "1 ", DateCreated = DateTime. now}, new Model. addressInfo {Address =" 2 ", DateCreated = DateTime. now });}

Then execute the Update-Database command again. In this way, you will no longer see the red error message.

Step 6

Wait for a moment. Now you suddenly think that some of your data must be transferred from the outside, but some of the DateCreated external data is NULL! What should you do if you don't want to, or cannot modify the information?

Perhaps you may think of a opportunistic method, that is, to secretly change the DateCreated column definition of the database from not null to NULL. However, if you are not a single expert, you should follow the original rules first, and do not want to perform special effects and make the most of them.

Like the previous practice, we first change the type of DateCreated from "DateTime" to "DateTime? ", Then execute the Add-Migration SetDateCreatedToNullable command, and then execute the Update-Database command. Then, we can see that the DateCreated column has been set to NULL in the database.

Similarly, we also check whether a xxx_SetDateCreatedToNullable record is added to the _ MigrationHistory table in the database.

Step 7

Now, assuming that your external data has been imported, there will be no need to import external data in the future, and you want to change DateCreated to not null. So, now we take the type of DateCreated from "DateTime? "Change back to" DateTime ", then execute the Add-Migration SetDateCreatedAgain command, and then execute the Update-Database command.

Of course, you must not forget to check whether the DateCreated column of the data in the database is NULL. If any, fill in a preset value for them. If you do not, an error occurs when you execute the Update-Database command.

Similarly, we can check whether a xxx_SetDateCreatedAgain record is added to the _ MigrationHistory table in the database.

Step 8

Unfortunately, PM is here to tell you that he thinks it is better to maintain NULL for DateCreated, because he cannot guarantee that no external information will be sent in the future; if you keep the value of the DateCreated field of the data to NULL, you can determine whether the data is originally unknown when it will be created.

He is talking about it all. It doesn't matter. We have a solution. But do you need to create another Migration? No. In the previously created Migration, one of them is to make the value of the DateCreated column NULL, and we do not need to create an identical Migration. The Update-Database command allows us to select from previous Migration operations.

First, you can see the previous Migration from the Migration folder in the project, but you can also directly run the Get-Migrations command to list all previous Migrations:

 

From this list, we can see that from step 1 to Step 7, we have created a total of four Migration:

201404240923456_SetDateCreatedAgain
201404240917497_SetDateCreatedToNullable
201404240809403_AddDateCreated
201404240554516_CreateDb
The first item (201404240923456_SetDateCreatedAgain) is the Migration we created in Step 7. What we need to do now is restore to the Migration (201404240917497_SetDateCreatedToNullable) We created in Step 6 ). The command is as follows:

Update-Database-TargetMigration 201404240917497_SetDateCreatedToNullable

 

This command specifies the execution object of the Update-Database and restores the Migration after it. After the command is executed, EF restores the Migration SetDateCreatedAgain to the Migration SetDateCreatedToNullable. If you execute the Get-Migrations command again, you will find that there are only three items left. In addition, if you go to the database to view the _ MigrationHistory data table, there are only three records left in it.

Of course, when performing various Migration jobs, you must determine two things:

The Migration action must be consistent with your data model. For example, your Migration aims to set the DateCreated column to NULL, but you forgot to specify the type of the DateCreated column as "DateTime? ", Or you have changed the structure from the database without authorization. This is not correct.
The Migration You Want To Do cannot conflict with the existing data in the database. For example, if you set DateCreated to not null, but the DateCreated column of data in your Database is NULL, the Update-Database Command will issue an error during execution.
Conclusion

This article teaches EF Code First Step by step. It takes a long time to write, and you cannot skip any step or detail. Otherwise, the process may fail. If you find any problem in a specific Step, I suggest you delete the old database, recreate the project, and redo it from Step 1.

For friends who are not familiar with EF or Code First, this teaching may have a heavy burden on you. But don't be afraid of trouble. Because after you finish Step 1 and even repeat several times, you will find that this example project is really simple. After you get familiar with it, you will find it takes less than half an hour or even shorter to start from scratch.

However, since EF is still being revised, VS will also be changed. I don't know when the above steps or instructions will suddenly change. If you find any problems, please report them to me. In addition, I may modify this article at any time and add something I did not expect.

Address: http://www.dotblogs.com.tw/johnny/archive/2014/04/23/manual-entity-framework-migrations.aspx

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.