《ASP.NET MVC3高级编程》学习笔记2

我的目标是月底前看完。今天偷懒了,只看了一点。

 

第4章:模型

 

Asp.Net MVC中的模型指是那些发送信息到数据库,执行业务计算并在视图中渲染的模型对象。

这些对象代表应用程序关注的领域,模型就是程序里想要保持、创建、更新和删除的对象。

 

基架:

使用工具为每个模型对象的索引、创建、编辑和删除等功能构建控制器和视图的过程称为基架(scaffolding)。基架不是必须的,但是可以省下很多时间。(其实就是代码生成器了)

 

在创建Controller的对话框中可以选择基架。

Asp.Net MVC中的默认基架可以为应用程序的CRUD生成所需的样板代码。

如果不喜欢默认的代码生成机制,也可以自定义或者使用NuGet搜索scaffolding来查找可替代的模版。

 

实体框架:

可以从这里学习EF

http://msdn.microsoft.com/en-us/data/aa937723

http://www.cnblogs.com/haogj/archive/2011/05/06/2038965.html

 

Asp.Net 3 Tool Update之后新建的项目会包含EF4.1,并有基于EF的基架,当然完全可以去掉。

EF是一个ORM框架,不但可以保存.Net对象到数据库,而且可以利用Linq来检索这些数据。

 

EF4.1支持代码优先,指在不创建数据库、不打开VS设计器的情况下栽Sql Server中存储或检索信息。可以直接编写存.Net类,EF知道如何保存到正确位置。

代码优先风格和Asp.Net MVC一样,遵照了很多的约定来生成数据库。如名为id的属性会被映射为主键,Album会被保存在Albums表中。

适合从0开始编写应用程序。

 

MVC结合EF的例子:

1、先创建几个模型

1public class Album 2{ 3 public virtual int AlbumId { get; set; } 4 public virtual int GenreId { get; set; } 5 public virtual int ArtistId { get; set; } 6 public virtual string Title { get; set; } 7 public virtual decimal Price { get; set; } 8 public virtual string AlbumArtUrl { get; set; } 9 public virtual Genre Genre { get; set; } 10 public virtual Artist Artist { get; set; } 11} 12public class Artist 13{ 14 public virtual int ArtistId { set; get; } 15 public virtual string Name { get; set; } 16} 17public class Genre 18{ 19 public virtual int GenreId { set; get; } 20 public virtual string Name{ set; get; } 21} 22

 

创建的Model属性时候使用virtual不是必须的,但是可以打开EF的一些特性,如高效的修改跟踪机制(对EF没研究,没看懂,过后研究)

 

2、使用EF的代码优先时需要从EF的DbContext类派生出一个类来访问数据库,在访问数据库时候只需要实例化这个类就行。

派生类具有多个DbSet<T>字段,每个T代表一个要保存的对象,如下(可以不写,在添加Controller时候选择新建,让基架自己生成):

1public class MusicStoreDB : DbContext 2{ 3 public DbSet<Album> Albums { get; set; } 4 public DbSet<Genre> Genres { get; set; } 5 public DbSet<Artist> Artists { get; set; } 6} 7

 

3、使用自带的基架模版生成代码

 

4、生成的Controller的代码片段:

1private MusicStoreDB db = new MusicStoreDB(); 2 3public ViewResult Index() 4{ 5 var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist);//预加载 6 return View(albums.ToList()); 7} 8 9[HttpPost] 10public ActionResult Edit(Album album) 11{ 12 if (ModelState.IsValid)//验证模型修改的有效性 13 { 14 db.Entry(album).State = EntityState.Modified; 15 db.SaveChanges(); 16 return RedirectToAction("Index"); 17 } 18 ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "GenreId", album.GenreId); 19 ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId); 20 return View(album); 21} 22

Include方法表示采用预加载策略,把关联的数据尽可能的全加载进来。延迟加载的每一条记录在访问子对象时候会往数据库多发出一个额外的查询!

反之是延迟加载:

1var albums = db.Albums//延迟加载 2

*** ***

5、生成的编辑Action代码中,子对象使用ViewBag传值,对应的View子对象使用DropDownList提供选择。

这里可以考虑创建ViewModel,使用强类型视图(没有好不好之说,看是否合适)。

** **

6、运行之前需要往web.config里加入一个连接字符串

1<connectionStrings> 2 <add name="MusicStoreDB" 3 connectionString="data source .................." 4 providerName="System.Data.SqlClient" /> 5</connectionStrings>  6

这样运行起来,数据库中就会自动生成一个对应Model关系的数据库了。

 

 

Model和数据库的同步:

如果修改Model,EF要嘛重新创建数据库,要嘛就抛异常。

重建数据库需要提供一个数据库初始化器,如下:

1Database.SetInitializer(new DropCreateDatabaseAlways<MusicStoreDB>()); 2//框架提供两个IDatabaseInitializer的实现类: 3//DropCreateDatabaseAlways和DropCreateDatabaseIfModelChanges,见名知意 4

 

可以重写IDatabaseInitializer的Seed方法,为生成的数据库添加基本数据。

** **

ModelBinder:

MVC框架可以为不同类型的模型注册多个ModelBinder,默认实现是DefaultModelBinder。

DefaultModelBinder将检查参数声明的类型,从请求中将命名符合约定的值注入到一个相应的对象中。

例如,ModelBinder看到参数为Album,而Album有Title属性时,就会在请求中找到名为Title的参数,填入。

 

ModelBinder使用IValueProvider,在请求的不同区域查找参数。可以查看路由数据、查询字符串、表单数据等,也可自定义IValueProvider,后面章节有。

 

模型邦定可能存在安全性问题,比如修改到不能修改的属性,叫做over-posting攻击,预防方法后面章节有。

 

当Action中有参数时候,ModelBinder会隐式工作,也可以使用Controller中的UpdateModel和TryUpateModel方法显示地调用模型 绑定 。这两个方法关系到验证的问题,使用起来和int.Parse与int.TryParse一样。调用 TryUpateModel后直接查看ModelState.IsValid也能查看是否绑定成功。

代码交流 2021