zoukankan      html  css  js  c++  java
  • 一个小Forum Web程序示例,SqlForumRepository,LazyList和PagedList(Part 3)

    好久没写了。接着前面的来:

    一个小Forum Web程序示例,ASP.NET MVC Framework,总体结构介绍(Part 1)

    一个小Forum Web程序示例,ASP.NET MVC Framework,TDD简介(Part 2)

    上一部分写得太长太详细,这次争取描述清楚的前提下,写简短一点。

    上部分中,简单介绍了TDD流程,并创建了一些测试,这部分我将进一步完善,开始实现真实的SqlFourmRepository。

    另外简单介绍一个延迟加载的LazyList<T>和MVC分页很方便的PagedList<T>(末尾处有改进的PageList<T>)。

    按照惯例,先放个数据库结构图:

    image

    还是一如既往的简单,使用了Membership,创建了数据库关系。

    这里描述一下:Post表中的ParentId如果为Guid.Empty(00000000-0000-0000-0000-000000000000),表示这个帖子是主贴,如果为其他Post的Id,表示回帖,其他一概从简。

    下面是当前的IForumRepository,定义了一些方法,并在SqlForumRepository中实现这些没有被实现的方法。

    image 

    打开dbml文件,把需要用的几个表,都拖进去:

    image

    再看看我们之前的通用Models,这两种实体是不同的,在ForumService中,需要的是Models.Post和Models.Category,在SqlForumRepository中,我们需要查询LinqToSqlClasses实体,而返回的却是Model.Post(需要做一个转换)。

    image

    以AddPost(Models.Post post)为例,现在可以开始编写测试了:

    image

    这个测试中,创建了一个Post,并尝试提取它(GetPost方法我之前已经实现了)。

    在Assert中,严谨的做法应该是对比这两个对象(创建的post和从数据库中提取的actual),不过Assert.AreEqual方法对比引用类型总是会亮灯,只有重写Post类的Equals方法,在里面分别对比每个属性才行;或者在测试中一个一个去Assert,这样太麻烦了。仅仅是为了测试重写Equals方法,我的做法是:调试这个测试方法,在调试的时候查看是否有漏掉的,没有问题的话,就简单的Assert一下。(不知道正确否?请各位前辈们指点。)

    现在运行这个测试,亮灯,因为方法还没实现。

    image

    现在实现这个方法,测试,通过了。

    现在如法炮制,实现IForumService的其他所有方法,并保证测试通过就行了。

    注意:

    image 

    含有一个Models.Post的列表,我这里使用的是LazyList<Models.Post>类型(有关LazyList请看这里:Lazy Loading With The LazyList),它不会像ToList()那样被执行,仍然维持IQueryable状态,不会立即查询数据库,LazyList很适合用来处理一对多延迟查询的情况。

    这样的查询像这样写就完全OK了(这里的GetPost同样返回的IQueryable<Models.Post>):

    image

    还有一种多对一的情况。通过Post反向查找Category,如果仍然用LazyList会让人和迷惑,所以我也很迷惑,写个延迟加载的Category?晕乎乎。所以就干脆省略掉,Post中始终是有CategoryId的。

    LazyList<Post>的分页怎么办?

    这里有个古老的MVC分页PagedList<T>,在很早之前Scott Hanselman的视频里就是用了这个类,不过它是继承List<T>的,所以它不会被延迟执行。在我们这个方案中,它不应该属于SqlForumRepository,不过这里顺带一起介绍了吧。

    这个PagedList<T>(原版)有点小bug(判断分页那里),嘿嘿,还有一种改进型的PagedList<T>,因为不记得在哪里找到的了,所以我直接贴出来:

        public interface IPagedList
        
    {
            
    int TotalCount getset; } 

            
    int PageIndex getset; } 

            
    int PageSize getset; } 

            
    bool IsPreviousPage get; } 

            
    bool IsNextPage get; }
        }
     

        
    public class PagedList<T> : List<T>
        
    {
            
    public PagedList(IQueryable<T> source, int index, int pageSize)
            
    {
                TotalCount 
    = source.Count();
                PageSize 
    = pageSize;
                PageIndex 
    = index;
                AddRange(source.Skip((index 
    - 1)*pageSize).Take(pageSize).ToList()); 

                
    int pageResult = 0;
                
    for (int counter = 1; pageResult < TotalCount; counter++)
                
    {
                    pageResult 
    = counter*PageSize;
                    TotalPages 
    = counter;
                }

            }
     

            
    public int TotalPages getset; } 

            
    public int TotalCount getset; } 

            
    public int PageIndex getset; } 

            
    public int PageSize getset; } 

            
    public bool HasPreviousPage
            
    {
                
    get return (PageIndex > 1); }
            }
     

            
    public bool HasNextPage
            
    {
                
    get return (PageIndex*PageSize) < TotalCount; }
            }

        }
     

        
    public static class Pagination
        
    {
            
    public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int index, int pageSize)
            
    {
                
    return new PagedList<T>(source, index, pageSize);
            }
     

            
    public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int index)
            
    {
                
    return new PagedList<T>(source, index, 10);
            }
     

            
    public static PagedList<T> ToPagedList<T>(this LazyList<T> source, int index, int pageSize)
            
    {
                
    return new PagedList<T>(source.AsQueryable(), index, pageSize);
            }
     

            
    public static PagedList<T> ToPagedList<T>(this LazyList<T> source, int index)
            
    {
                
    return new PagedList<T>(source.AsQueryable(), index, 10);
            }

        }
     

    改进版的首先是让页面从1开始,而不是0开始,让用户不会因为第一页是0而迷惑,第二是改变原先的IsNextPage方法名称为HasNextPage,我这里采用的改进版,并添加了两个针对LazyList的扩展方法。

    暂时写到这里吧,感觉好像讲得不是很明白。ForumService没什么写头,好像剩下的就只有Controller和Membership了,介绍这方面的帖子很多,我想通过TDD(发挥MVC的优势)这样的角度来写吧,并和大家探讨一下使用Moq测试框架。

  • 相关阅读:
    在Myeclipse中配置tomcat
    tomcat用startup.bat启动时,界面一闪消失
    单向链表的基本操作
    简单排序的对比
    关于string的排序 选择插入排序
    insertsort
    selectsort
    理解函数式编程
    vue中使用$nextTick后任然无法正确计算出元素高度
    使用vuex+vue-i18n方式国际化
  • 原文地址:https://www.cnblogs.com/darkdawn/p/1303821.html
Copyright © 2011-2022 走看看