ASP.NET MVC Code First要点

来源:互联网 发布:网络技术交流论坛 编辑:程序博客网 时间:2024/05/21 06:26

1.新建Web项目-空的MVC项目MvcMusicStore

2.创建各个实体Models:

    public class Album    {        public int AlbumId { get; set; }        public int GenreId { get; set; }        public int ArtistId { get; set; }        public string Title { get; set; }        public decimal Price { get; set; }        public string AlbumArtUrl { get; set; }        public virtual Genre Genre { get; set; }        public virtual Artist Artist { get; set; }    }
   public partial class Genre    {        public int GenreId { get; set; }        public string Name { get; set; }        public string Description { get; set; }        public List<Album> Albums { get; set; }    }

    public class Artist    {        public int ArtistId { get; set; }        public string Name { get; set; }    }

3.web.config配置连接字符串:

<connectionStrings>    <add name="<strong>MusicStoreEntities</strong>"     connectionString="server=.;database=<strong>MvcMusicStore</strong>;uid=sa;pwd=123456;Integrated Security=True"     providerName="System.Data.SqlClient" />  </connectionStrings>  

4.创建数据上下文实体类MusicStoreEntities(名称跟连接字符串名称一致),继承自DbContext:

 public class <strong>MusicStoreEntities </strong>: DbContext    {        //public MusicStoreEntities()        //    : base("name=<strong>MusicStoreEntities</strong>")//如果连接字符串名字和类名MusicStoreEntities一致,则可不写: base("name=MusicStoreEntities")。        //{        //    this.Database.CreateIfNotExists();        //}        public DbSet<Album> Albums { get; set; }        public DbSet<Genre> Genres { get; set; }        public DbSet<Artist> Artists { get; set; }    }
5.Global.asax-->Application_Start事件中初始化数据库策略:
protected void Application_Start()        {            Database.SetInitializer(new MvcMusicStore.Models.SampleData());//当提供了初始化数据时,使用该形式,以初始化数据库策略并填充一些数据(当某个Model改变了,就删除原来的数据库创建新的数据库)            //Database.SetInitializer<MvcMusicStore.Models.MusicStoreEntities>(new DropCreateDatabaseIfModelChanges<MvcMusicStore.Models.MusicStoreEntities>());//没提供数据库初始化数据时使用该形式            AreaRegistration.RegisterAllAreas();            RegisterGlobalFilters(GlobalFilters.Filters);            RegisterRoutes(RouteTable.Routes);        }

6.为数据库创建初始化数据(可选):

<pre class="csharp" name="code">public class SampleData : DropCreateDatabaseIfModelChanges<MusicStoreEntities>    {        protected override void Seed(MusicStoreEntities context)        {            //base.Seed(context);            var genres = new List<Genre>            {                new Genre { Name = "Rock" },                new Genre { Name = "Jazz" },                new Genre { Name = "Metal" },                new Genre { Name = "Alternative" },                new Genre { Name = "Disco" },                new Genre { Name = "Blues" },                new Genre { Name = "Latin" },                new Genre { Name = "Reggae" },                new Genre { Name = "Pop" },                new Genre { Name = "Classical" }            };            genres.ForEach(u => context.Genres.Add(u));//每次创建数据库时,都会为该表添加这些初始化数据       }    }

7.View 页面:

 DropDown的使用:

首先在controller中建立dropdown的数据源 (通过键 “GenreId”,"ArtistId" 与页面中的对应Id来对应到dropdown)

 ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name"); ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");
在view中显示dropdown:

 @Html.DropDownList("GenreId", String.Empty)

-------------------以上仅供个人记录使用--------------------

  var genresModel = storeDB.Genres.Include("Albums").SingleOrDefault(g=>g.Name==genre);//include可以获取Genres中的其他对象,如Albums对象  var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist);

8.数据迁移Migration:(将Model的修改应用到数据库中,且不会改变对应的表中的原始数据)

8.1:新建控制台应用程序MigrationDemo.

8.2:获取最新EntityFrameWork包:Tools –> Library Package Manager –> Package Manager Console,执行命令:Install-Package EntityFramework

8.3:新建Model:Blog.cs, 和DbContext:BlogContext

public class Blog    {        public int BlogId { get; set; }        public string Name { get; set; }     }
public class <strong>BlogContext</strong>:DbContext    {       public DbSet<Blog> Blogs { get; set; }    }
8.4:app.config 配置连接字符串:

<add name="<strong>BlogContext</strong>" connectionString="server=.;database=<strong>BlogDatabase</strong>;uid=sa;pwd=123456;Integrated Security=True" providerName="System.Data.SqlClient" />

8.5:Program.cs:

<pre name="code" class="csharp">static void Main(string[] args)        {            using (BlogContext db = new BlogContext())            {                db.Blogs.Add(new Blog { Name="Test1"});                db.SaveChanges();                foreach (var item in db.Blogs)                {                    Console.WriteLine(item.Name);                }            }            Console.ReadKey();        }

8.6:运行程序:

程序自动创建数据库BlogDatabase。

8.7:启用数据迁移:

    在Package Manager Console中执行命令:Enable-Migrations

    程序自动在项目中新增文件夹Migrations:


同时数据库中自动建立一个表.__MigrationHistory:


8.8:修改Model:为Blog.cs增加一个属性:

public string Url { get; set; }

8.9:执行Migration命令:

Add-Migration: will scaffold the next migration based on changes you have made to your model since the last migration was created.

Update-Database: will apply any pending migrations to the database.

首先执行命令:Add-Migration AddBlogUrl,此时在Migrations文件夹中新增一个migration类:201606250908432_AddBlogUrl.cs:(前缀是时间戳)

然后执行命令:Update-Database

    Code First Migrations will compare the migrations in our Migrations folder with the ones that have been applied to the database. It will see that theAddBlogUrl migration needs to be applied, and run it.

此时,Blog表已经增加了字段:Url.

zhulongxi


8.9:自定义Migration:

以上Migration都是没有对Migration生成的文件进行修改而使用默认的code来进行Migration的。以下对Migration生成的code作适当修改后再进行Migration:

--》对Blog.cs新增一个属性

public int Rating { get; set; }
--》新增一个class:Post.cs:

public class Post {     public int PostId { get; set; }     [MaxLength(200)]     public string Title { get; set; }     public string Content { get; set; }      public int BlogId { get; set; }     public Blog Blog { get; set; } }
--》在Blog.cs中增加与Post的对应关系的集合:

public virtual List<Post> Posts { get; set; } 
--》在BlogContext中添加Post集合:

public DbSet<Post> Posts { get; set; }

--》执行命令:Add-Migration AddPostClass
此时在Migrations文件夹中生成201606250923576_AddPostClass.cs,对其做一些修改:

-对Posts.Title建立索引

-设置Blogs.Rating的默认值为3

public partial class AddPostClass : DbMigration    {        public override void Up()        {            CreateTable(                "dbo.Posts",                c => new                    {                        PostId = c.Int(nullable: false, identity: true),                        Title = c.String(maxLength: 200),                        Content = c.String(),                        BlogId = c.Int(nullable: false),                    })                .PrimaryKey(t => t.PostId)                .ForeignKey("dbo.Blogs", t => t.BlogId, cascadeDelete: true)                .Index(t => t.BlogId)                .Index(t=>t.Title,unique:true);                        AddColumn("dbo.Blogs", "Rating", c => c.Int(nullable: false,defaultValue:3));        }                public override void Down()        {            DropForeignKey("dbo.Posts", "BlogId", "dbo.Blogs");            DropIndex("dbo.Posts", new[] { "Title" });            DropIndex("dbo.Posts", new[] { "BlogId"});            DropColumn("dbo.Blogs", "Rating");            DropTable("dbo.Posts");        }    }
--》执行Update-Database命令,为了能看到SQL执行语句,Update-Database –Verbose命令代替Update-Database命令,

此时数据库产生相应的修改:


此时blogs表中的数据不变,只是增加了一列Rating,默认值为3:


8.10.在Migration的过程中使用自定义SQL:

-为Post.cs添加一个属性:

 public string Abstract { get; set; }
-执行命令:Add-Migration AddPostAbstract

-在生成的Migration文件中进行适当修改:

public partial class AddPostAbstract : DbMigration     {         public override void Up()         {             AddColumn("dbo.Posts", "Abstract", c => c.String());              <strong>Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL"); </strong>//使Abstract列取Content列的值的前100个字符        }                  public override void Down()         {             DropColumn("dbo.Posts", "Abstract");         }     } 

-执行命令:Update-Database –Verbose

-此时数据库进行了相应的修改:


8.11.使用Migration使数据库回退到之前的某一个状态:

比如想要让数据库状态回到执行了AddBlogUrl 后的状态:使用Update-Database –TargetMigration: AddBlogUrl,此时数据库只剩下Blogs表:


如果想让数据库恢复到空的状态,使用Update-Database –TargetMigration: $InitialDatabase,此时数据库的表全部没了:


8.12.生成Migration过程中的SQL script:

执行命令:Update-Database -Script -SourceMigration: $InitialDatabase -TargetMigration: AddPostAbstract:

SourceMigration:为要创建sql script的Migration的开始状态,TargetMigration:要创建sql script的Migratioin的最终版本。

执行后生成一个sqlQuery_1.sql文件。

8.13.在程序每次启动时自动应用所有的Migration从而更新数据库:

在global.asax 的Applicaton_Start事件中或Program.cs的main方法中加入:

 Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogContext, Configuration>());// Configuration为Migrations文件夹中的Configuration类
这样每当程序启动的时候,首先会数据库是否需要Migration,并且应用所有的migration。

https://msdn.microsoft.com/en-US/data/jj591621#model


0 0