一.IQueryable和IEnumerable的使用区别
使用IQueryable,EF会根据调用者的Linq表达式先生成相应的SQL查询语句,然后到数据库中执行查询,查询出来的数据即是用户想要的数据;
而使用IEnumerable,Linq表达式的过滤、排序等操作都是在内存中发生的,即EF会先从数据库中把整个表的数据查询出来放在内存中,然后由调用者使用Linq语句进行过滤、排序等操作。
IQueryable虽然可以很智能地根据Linq表达式生成相应的SQL语句,但毕竟有一个分析Linq表达式的过程,相对来说性能比IEnumerable要差。
使用:
对于少量的数据(比如从数据库中读取应用程序相关的系统信息)和不需要对数据进行过滤操作的情况,用IEnumerable比较适合;
对于数据量较大需要对数据进行过滤(比如分页查询)的情况,则用IQueryable比较合适。
二.URL定义
默认指向Home/Index
routes.MapRoute("MyRoute", "{controller}/{action}",new { controller="Home",action="Index"});
URL加上一个名为Public的固定前缀
routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });
可以把静态的字符串放在大括号以外的任何位置
routes.MapRoute("", "X{controller}/{action}", new { controller = "Home", action = "Index" });
在一些情况下这种定义非常有用。比如当你的网站某个链接已经被用户普遍记住了,但这一块功能已经有了一个新的版本,但调用的是不同名称的controller,那么你把原来的controller名称作为现在controller的别名。这样,用户依然使用他们记住的URL,而导向的却是新的controller。如下使用Shop作为Home的一个别名:
routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });
这样,用户使用原来的URL可以访问新的controller:
通过 catchall 片段变量加 * 号前缀来定义匹配任意数量片段的路由。
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
路由约束
正则表达式约束
通过正则表达式,我们可以制定限制URL的路由规则,下面的路由定义限制了controller片段的变量值必须以 H 打头:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new { controller = "^H.*" } );
定义路由约束是在MapRoute方法的第四个参数。和定义默认值一样,也是用匿名类型。
我们可以用正则表达式约束来定义只有指定的几个特定的片段值才能进行匹配,如下所示:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new { controller = "^H.*", action = "^Index$|^About$" } );
这个定义,限制了action片段值只能是Index或About,不区分大小写。
Http请求方式约束
我们还可以限制路由只有当以某个特定的Http请求方式才能匹配。如下限制了只能是Get请求才能进行匹配:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new { controller = "^H.*", httpMethod = new HttpMethodConstraint("GET") } );
通过创建一个 HttpMethodConstraint 类的实例来定义一个Http请求方式约束,构造函数传递是允许匹配的Http方法名。这里的httpMethod属性名不是规定的,只是为了区分。
这种约束也可以通过HttpGet或HttpPost过滤器来实现。
自定义路由约束
如果标准的路由约束满足不了你的需求,那么可以通过实现 IRouteConstraint 接口来定义自己的路由约束规则。
我们来做一个限制浏览器版本访问的路由约束。在MVC工程中添加一个文件夹,取名Infrastructure,然后添加一个 UserAgentConstraint 类文件,代码如下:
public class UserAgentConstraint : IRouteConstraint { private string requiredUserAgent; public UserAgentConstraint(string agentParam) { requiredUserAgent = agentParam; } public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { return httpContext.Request.UserAgent != null && httpContext.Request.UserAgent.Contains(requiredUserAgent); } }
这里实现IRouteConstraint的Match方法,返回的bool值告诉路由系统请求是否满足自定义的约束规则。我们的UserAgentConstraint类的构造函数接收一个浏览器名称的关键字作为参数,如果用户的浏览器包含注册的关键字才可以访问。接一来,我们需要注册自定的路由约束:
public static void RegisterRoutes(RouteCollection routes) { routes.MapRoute("ChromeRoute", "{*catchall}", new { controller = "Home", action = "Index" }, new { customConstraint = new UserAgentConstraint("Chrome") } ); }
下面分别是IE10和Chrome浏览器请求的结果:
List<Entity>添加Entity时候无法转换再foreach一次,select new Entity就好了