这里的“按需更新”指的是只更新被修改的数据。比如我们在博客后台打开随笔编辑页面,有很多数据可以修改,但我们只改了随笔标题,其他都没改,在保存时,数据库只进行标题字段更新的操作,这就是按需更新。
目前用的是很落后的方法,一个带有很多参数的存储过程,不管你修改了随笔的哪些信息,哪怕只改了一个标题,保存时对所有字段都要进行更新操作。
博客园现代化建设不只是口号,落后的地方都要努力去改变。
Entity Framework的一个特性让我们看到了希望,当时引进Entity Framework这个现代化装备还是值得的。
Entity Framework可以跟踪实体对象属性的变化,在保存到数据库时只更新被修改的属性。下面我们通过代码示例看一下Entity Framework的这个特性。
实体类BlogPost:
public class BlogPost
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Author { get; set; }
}
BlogDbContext:
public class BlogDbContext : DbContext
{
public DbSet<BlogPost> BlogPosts { get; set; }
}
数据更新操作:
BlogPost post = new BlogPost()
{
ID = 3560,
Title = "Title Test",
Description = "Description test",
Author = "博客园"
};
using (BlogDbContext context = new BlogDbContext())
{
context.BlogPosts.Attach(post);
post.Title = "Title Changed";
post.Description = "Description test";
context.SaveChanges();
}
这个数据更新操作只是为了更新了post的标题(只有标题被修改),我们看一下Entity Framework最终执行的SQL语句:
exec sp_executesql N'update [dbo].[blog_Content]
set [Title] = @0
where ([ID] = @1)
',N'@0 nvarchar(128),@1 int',@0=N'Title Changed',@1=3560
很强大吧,只更新了Title字段。
但是,理想与现实差距总是很大的,要想把这个强大的特性用在Web应用程序中,将面临很多挑战。
再看一下上面的数据更新代码:要在context的生命周期内,Attach修改前的实体对象,然后对这个实体对象进行修改,然后保存。
在Web应用场景中,你无法在context的生命周期内,将实体对象传递给客户端,在客户端进行修改。
而我们要面对的实际应用场景是这样的(ASP.NET MVC+ajax):
1. 客户端浏览器先向服务端发起一个请求,这个请求得到的是包含要修改的实体对象的原始属性值的页面,服务器端在context(BlogDbContext的实例)的生命周期内,完成一个查询操作。
2. 在客户端浏览器中修改相应的属性值。
3. 将所有属性值(修改和未修改的)以json格式发送给服务器。
4. 服务器端在Cotroller中根据客户端发送过来的json数据,创建包含修改和未修改的属性值的BlogPost实例——ModifiedBlogPost(如果没有缓存,要以从数据库查询的方式得到BlogPost实例,然后再将json数据赋值给对应的属性)。
5. 在业务逻辑层在context(一个新的BlogDbContext的实例)的生命周期内:
a) 获取修改前的BlogPost实例OriginalBlogPost(如果没有缓存,要从数据库查询);
b) Attach(OriginalBlogPost);
c) 将ModifiedBlogPost的所有属性值复制到OriginalBlogPost;
d) SaveChanges();
这个场景中存在的问题(重复的操作):
1. 第4项与5.a项中获取修改前的对象的操作。
2. 第4项与5.c项中对象属性赋值的操作。
准备尝试的解决方法:
将客户端发送过来的json数据直接以字符串的方式传递给业务逻辑层,然后在业务逻辑层根据json数据直接完成5.c中OriginalBlogPost的属性赋值操作。
这篇随笔记录的是博客园现代化建设过程中的一个片断,接下来,我们要攻克这个难题,继续努力...