关于数据库索引、接口与抽象类、MVC拦截器、URL传参数基本实现方式简单说明

版权声明:学习之路有很多引荐的地方,希望能帮到大家就可以! https://blog.csdn.net/mingzaiwang/article/details/83657583

写了四年代码,然后管理了两年团队,每次面试我都想说为什么总是问书本知识,后来一想算了社会就是这样的,我们不要刻意的去纠结关于这些知识,但是我们要顺应时代也要把这些询问知识点掌握牢靠。开始我的表演

1、数据库方面的索引的作用,以及申明的方法?

         我们暂时就用:“索引就像书的目录, 通过书的目录就准确的定位到了书籍具体的内容。”这句话来形容申明叫索引。

建表时候一定会有主键那么对应的就会有对应的聚集索引,从而就有了树状结构的数据表。通过每一个主键之间的主从关系的关联形成了一个临时性数据库(我们一般都会有主键,从而形成了对应的平衡树。)

那么问题了来了我们知道了聚集索引,从而就开始疑问什么叫非聚集索引呢?

非聚集索引叶节点仍然是索引节点,只是有一个指针指向对应的数据块,此如果使用非聚集索引查询,而查询列中包含了其他该索引没有覆盖的列,那么他还要进行第二次的查询,查询节点上对应的数据行的数据。

如有以下表t1:

id username score
1 小明 90
2 小红 80
3 小华 92
.. .. ..
256 小英 70

以及聚集索引clustered index(id), 非聚集索引index(username)。

使用以下语句进行查询,不需要进行二次查询,直接就可以从非聚集索引的节点里面就可以获取到查询列的数据。

select id, username from t1 where username = '小明'
select username from t1 where username = '小明'

但是使用以下语句进行查询,就需要二次的查询去获取原数据行的score:

select username, score from t1 where username = '小明'

复合索引(覆盖索引)

建立两列以上的索引,即可查询复合索引里的列的数据而不需要进行回表二次查询,如index(col1, col2),执行下面的语句

select col1, col2 from t1 where col1 = '213';

要注意使用复合索引需要满足最左侧索引的原则,也就是查询的时候如果where条件里面没有最左边的一到多列,索引就不会起作用。

在SQL Server中还有include的用法,可以把非聚集索引里包含的列包含进来,而不一定需要建立复合索引。

2、关于实际代码中c#接口与抽象类的区别?

接口和抽象类都具有

1、都可以被继承

2、都不能被实例化

3、都可以包含方法声明

4、派生类必须实现未实现的方法

接口就是接口(interface)就是一种规范,定义好了规范剩下的工作就会简单方便快捷。

这个是我2016年写的接口的实际例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<IShow> list = new List<IShow>();
            list.Add(new Map());
            list.Add(new Voice());
            list.Add(new Video());
            list.Add(new ThreeD());
            foreach (IShow ishow in list)
            {
                ishow.Show();
                Console.ReadKey();
            }
        }
    }
    interface IShow
    {
        void Show();
    }
    public class Map : IShow
    {
        public void Show()
        {
            Console.WriteLine("显示图片");
        }
    }
    public class Voice : IShow
    {
        public void Show()
        {
            Console.WriteLine("播放声音");
        }
    }
    public class Video : IShow
    {
        public void Show()
        {
            Console.WriteLine("显示视频");
        }
    }
    public class ThreeD : IShow
    {
        public void Show()
        {
            Console.WriteLine("3D交互");
        }
    }
    
}
public class Vm : IShow
{
        public void Show()
        {
            Console.WriteLine("vm感观");
        }
}

后来来了一个VM这个就是有了VR。

如果预计会出现版本问题,可以创建“抽象类”。例如,创建了狗(Dog)、鸡(Chicken)和鸭(Duck),那么应该考虑抽象出动物(Animal)来应对以后可能出现风马牛的事情。而向接口中添加新成员则会强制要求修改所有派生类,并重新编译,所以版本式的问题最好以抽象类来实现。

abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现。抽象方法的实现必须在派生类中使用override关键字来实现。
接口和抽象类最本质的区别:抽象类是一个不完全的类,是对对象的抽象,而接口是一种行为规范。

抽象类:

public abstract class Fruit
{
        public string  vendor { get; set; }   //默认为private
        
        public abstract float Price { get; }  //抽象属性必须是公有的

        public abstract void GrowInArea();    //抽象方法必须是公有的
}
public class Apple : Fruit
{
        public override float Price
        {
            get
            {
                if (vendor == "红富士")
                    return 100;
                else
                    return 0;

            }
        }

        public override void GrowInArea()
        {
            Console.WriteLine("我在南方北方都能生长,我的生产商是:" + vendor + ",我现在的价格        
            是:" + Price);
        }
}
static void Main(string[] args)
{
            Fruit f = new Apple();
            f.vendor = "红富士";
            f.GrowInArea();

            f = new Orange();
            f.vendor = "柑橘";
            f.GrowInArea();

            Console.ReadKey();

}

3、关于MVC中拦截器的使用?

     在ASP.NET MVC中,有三种拦截器:Action拦截器、Result拦截器和Exception拦截器。我要用到第一种和第三种。其实所谓的ASP.NET MVC拦截器,也没什么神秘的,就是一个普通的类而已。只不过需要继承FilterAttribute基类,Action拦截器还要实现IActionFilter接口,而Exception拦截器需要实现IExceptionFilter接口。
      我们先来看实现:让我们在Controllers目录下新建一个Filters目录,然后在Filters下新建两个类,一个叫LoggerFilter一个叫ExceptionFilter。首先是LoggerFilter的代码。

1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Web;
 5using System.Web.Mvc;
 6using System.Web.Mvc.Ajax;
 8namespace MVCDemo.Controllers.Filters
 9{
   public class LoggerFilter : FilterAttribute, IActionFilter
   {
       void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
       {
           filterContext.Controller.ViewData["ExecutingLogger"] = "正要添加公告,已以写入日志!时间:" + DateTime.Now; 
       }
17        void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
       {
           filterContext.Controller.ViewData["ExecutedLogger"] = "公告添加完成,已以写入日志!时间:" + DateTime.Now;
       }
   }
22}

 可以看到,这个类继承了FilterAttribute并实现了IActionFilter。其中关键是IActionFilter,它有两个方法,OnActionExecuting在被拦截Action前执行,OnActionExecuted在被拦截Action后执行。两个方法都有一个参数,虽然类型不同,但其实都是一个作用:被拦截Action的上下文。
      这个地方我得解释一下,你拦截器拦截了Action,在做处理时难免要用到被拦截Action相关的东西,例如在我们的例子中,就需要想被拦截Action所在Controller的ViewData中添加内容,所以,拦截器方法有一个参数表示被拦截Action的上下文是顺理成章的事。
      下面再看ExceptionFilter这个拦截器,它是在Action出现异常时发挥作用的。
ExceptionFilter.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
namespace MVCDemo.Controllers.Filters
{
   public class ExceptionFilter : FilterAttribute,IExceptionFilter
   {
       void IExceptionFilter.OnException(ExceptionContext filterContext)
       {
           filterContext.Controller.ViewData["ErrorMessage"] = filterContext.Exception.Message;
           filterContext.Result = new ViewResult()
           {
               ViewName = "Error",
               ViewData = filterContext.Controller.ViewData,
           };
           filterContext.ExceptionHandled = true;
       }
   }
}

完整实例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using MVCDemo.Models;
using MVCDemo.Models.Interfaces;
using MVCDemo.Models.Entities;
using MVCDemo.Controllers.Filters;
namespace MVCDemo.Controllers
{
   public class AnnounceController : Controller
   {
       public ActionResult Release()
       {
           ICategoryService cServ = ServiceBuilder.BuildCategoryService();
           List<CategoryInfo> categories = cServ.GetAll();
           ViewData["Categories"] = new SelectList(categories, "ID", "Name");
           return View("Release");
       }
       [LoggerFilter()]
       [ExceptionFilter()]
       public ActionResult DoRelease()
       {
           AnnounceInfo announce = new AnnounceInfo()
           {
               ID = 1,
               Title = Request.Form["Title"],
               Category = Int32.Parse(Request.Form["Category"]),
               Content = Request.Form["Content"],
           };
           IAnnounceService aServ = ServiceBuilder.BuildAnnounceService();
           aServ.Release(announce);
           ViewData["Announce"] = announce;
           System.Threading.Thread.Sleep(2000);
           ViewData["Time"] = DateTime.Now;
           System.Threading.Thread.Sleep(2000);
           return View("ReleaseSucceed");
       }
   }
}

4、session与cookie的差距,为什么要用session,cookie实际操作的具体每一个方法,并且还说下token?

  1. cookie数据存放在客户的浏览器上,session数据放在服务器上。
  2. cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 ,考虑到安全应当使用session。
  3. session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
  4. 考虑到减轻服务器性能方面,应当使用COOKIE。
  5. 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
  6. 所以个人建议:
  7.    将登陆信息等重要信息存放为SESSION
  8.    其他信息如果需要保留,可以放在COOKIE中

session 和 oauth token并不矛盾,作为身份认证 token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击,而session就必须靠链路层来保障通讯安全了。如上所说,如果你需要实现有状态的会话,仍然可以增加session来在服务器端保存一些状态

App通常用restful api跟server打交道。Rest是stateless的,也就是app不需要像browser那样用cookie来保存session,因此用session token来标示自己就够了,session/state由api server的逻辑处理。 如果你的后端不是stateless的rest api, 那么你可能需要在app里保存session.可以在app里嵌入webkit,用一个隐藏的browser来管理cookie session.

token就是登陆的令牌,避免重复登陆和反复获取session带给服务器的压力等。

5、对应页面相互之间传递参数有那些方法和对应这些方法的优缺点?

1、url方式  http://abc.com?name=xiaoming&age=18&gender=man

2、使用cookie保存:

//1、保存一条数据
document.cookie="name=abc";
document.cookie="age=18";
//2、获取所有数据
var cookie=document.cookie;
console.log(cookie);  //"name=abc; age=18; PHPSESSID=fr1njdv6apf3neoj5nehntrps7"
//之后可以解析字符串,获取指定的数据内容
//3、设置cookie的有效期
document.cookie="id=666;expires="+new Date("2017-10-22 08:00");
 //第一种类型:会话cookie
//    //1、设置值
    $.cookie("phone","13188886666");
    $.cookie("email","[email protected]");
//    //2、获取值
    var phone=$.cookie("phone");
    console.log(phone);
    var email=$.cookie("email");
    console.log(email);
    //第二种类型:设置长期cookie(具有指定有效期)
    $.cookie("address","广东深圳市",{
        expires:7               //expires不仅仅可以是日期类型的对象,也可以是以天为单位的数字
    });
    $.cookie("tel","0755-88888888",{
        expires:1/24              //该cookie值就会保存一小时
    });
    $.cookie("birthday","1.1",{
        expires:new Date("2018-01-01 08:00")        //对于这样的过期时间,已经在内部处理好了时区问题
    });
//删除指定的cookie
$.removeCookie("birthday");

3、使用h5的localStorage,或者sessionStorage存储对象类型

存储对象的正确的方式:
var p2={name:"周瑜",age:16};
var s2=JSON.stringify(p2);      //将对象"序列化"为JSON数据(字符串格式)
localStorage.setItem("p2",s2);  //以字符串格式存储信息
var s2_2=localStorage.getItem("p2");    //获取存储的信息,也是字符串格式
var p2_2=JSON.parse(s2_2);      //将JSON数据反序列化为对象

localStroage和sessionStorage使用大致相同,他们的不同之处在于,localstroage是永久保存,而sessionstroage是会话存在,
当会话结束,sessionstroage保存值也会清空。

猜你喜欢

转载自blog.csdn.net/mingzaiwang/article/details/83657583