笔记07ASP.NET MVC最新版

第二章:Action参数及ActionResult
 
第三章:layout-Html辅助方法-数据验证

5.如何判断请求来自ajax

hmtl代码

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>AJAX</title>
    <script src="~/jquery-1.8.3.js"></script>
    <div>
        <script type="text/javascript">
        $(function () {
            $("#btn").click(function () {
                $.ajax({
                    dataType: "json",
                    type: "GET",
                    url: "/Test/AJAX2",
                    success: function (res) {
                        alert(res);
                        alert(res.msg);
                    },
                    error: function (err) {
                        alert("提交异常");
                        alert(err.msg);
                    },
                });
            });
        });

        </script>
    </div>
</head>
<body>
    <div> 
        <input type="button" id="btn" value="点我"/>
    </div>
</body>
</html>
View Code

c#代码(注意,如果ajax是get请求,c#得这样设置Json(new { state = "1001", msg = "err" }, JsonRequestBehavior.AllowGet),,,post无视)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace _03_05_如果判断请求来自ajax.Controllers
{
    public class TestController : Controller
    {
        // GET: Test
        public ActionResult Index()
        {
            return View();
        }
        public ActionResult AJAX()
        {
            return View();
        }
        public ActionResult AJAX2()
        {
            if (Request.IsAjaxRequest())
            {
                return Json(new { state = "1000", msg = "ok" }, JsonRequestBehavior.AllowGet);
            }
            else
            {
                return Json(new { state = "1001", msg = "err" }, JsonRequestBehavior.AllowGet);
            }

        }
    }
}
View Code

 6.数据验证基础

获取验证错误信息

c#

        // GET: Val1
        public ActionResult Index(IndexModel model)
        {
            //参数校验是否通过
            if (ModelState.IsValid)
            {
                return Content("Age=" + model.Age);
            }
            else
            {
                string msg = MVCHelper.GetValidMsg(ModelState);
                return Content("err->" + msg);
            }

        }
View Code

MVCHelper

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace _03_06_数据验证基础
{
    public static class MVCHelper
    {
        public static string GetValidMsg(ModelStateDictionary modelState)
        // 有两个ModelStateDictionary 类,别弄混乱了。要使用 System.Web.Mvc 下的
        {
            StringBuilder sb = new StringBuilder();
            foreach (var key in modelState.Keys)
            {
                if (modelState[key].Errors.Count <= 0)
                {
                    continue;
                }
                sb.Append("属性【").Append(key).Append("】错误:");
                foreach (var modelError in modelState[key].Errors)
                {
                    sb.AppendLine(modelError.ErrorMessage);
                }
            }
            return sb.ToString();
        }
    }
}
View Code

 7.数据验证Attribute

/*
  ASP.Net MVC 提供了在服务器端验证请求数据的能力。要把对应的 Attribute 标记到 Model 的属性上(标记到方法参数上很多地方不起作用)。

常用验证 Attribute:

a) [Required] 这个属性是必须的

b) [StringLength(100)],字符串最大长度 100;[StringLength(100,MinimumLength=10)] 长度要介于 10 到 100 之间

c) [RegularExpression(@"aa(\d)+bb")] 正则表达式

d) [Range(35,88)] 数 值 范 围 。 字 符 串 长 度 范 围 的 话 请 使 用 [StringLength(100,MinimumLength=10)]

e) [Compare("Email")]这个属性必须和 Email 属性值一样。

f) [EmailAddress] 要是邮箱地址

g) [Phone]电话号码,规则有限

3)验证 Attribute 上都有 ErrorMessage 属性,用来自定义报错信息。ErrorMessage 中可以用 {0}占位符作为属性名的占位。

4)数据验证+Html 辅助类高级控件可以实现很多简化的开发,连客户端+服务器端校验都自 动实现了,但是有点太“WebForm”了,因此这里先学习核心原理,避免晕菜。
*/
    public class IndexModel
    {
        public int Age { get; set; }
        public long Id { get; set; }
        [Required(ErrorMessage ="手机号必填")]
        public string PhoneNum { get; set; }
        public string PassWord { get; set; }
        [Compare("PassWord", ErrorMessage = "两次密码输入的必须一致")]
        public string PassWord2 { get; set; }

        [EmailAddress(ErrorMessage = "请输入正确的Email地址")]
        public string Email { get; set; }
    }
View Code

 8.自定义验证规则

    public class IndexModel
    {
        public int Age { get; set; }
        public long Id { get; set; }
        [CNPhoneNum]
        public string PhoneNum { get; set; }
        public string PassWord { get; set; }
        [Compare("PassWord", ErrorMessage = "两次密码输入的必须一致")]
        public string PassWord2 { get; set; }

        [EmailAddress(ErrorMessage = "请输入正确的Email地址")]
        public string Email { get; set; }
        [QQNumber]
        public string QQ { get; set; }
    }
View Code
   public class CNPhoneNumAttribute : ValidationAttribute
    {
        public CNPhoneNumAttribute()
        {
            this.ErrorMessage = "电话号码必须是固话或者手机,固话要是3-4位区号开头,手机必须以13、15、18、17开头";
        }
        //注意,不要override ValidationResult IsValid(object value, ValidationContext validationContext)
        public override bool IsValid(object value)
        {
            if (value is string)
            {
                string s = (string)value;

                if (s.Length == 13)//手机号
                {
                    if (s.StartsWith("13") || s.StartsWith("15") || s.StartsWith("17") || s.StartsWith("18"))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else if (s.Contains("-"))//固话
                {
                    //010,021 0755 0531
                    string[] strs = s.Split('-');
                    if (strs[0].Length == 3 || strs[0].Length == 4)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
    }
View Code
    public class QQNumberAttribute:RegularExpressionAttribute
    {
        public QQNumberAttribute():base(@"^\d{5,11}$")
        {
            this.ErrorMessage = "字段{0}不是合法的QQ号,QQ号长度在5-11位";
        }
    }
View Code

 

第四章:Filter和NuGet

 过滤器Filter

AOP(面向切面编程)是一种架构思想,用于把公共的逻辑放到一个单独的地方,这样
就不用每个地方都写重复的代码了。比如程序中发生异常,不用每个地方都 try...catch...只
要在(Global 的 Application_Error)中统一进行异常处理。不用每个 Action 中都检查当前
用户是否有执行权限,ASP.net MVC 中提供了一个机制,每个 Action 执行之前都会执行我们的代码,这样统一检查即可。
一夫当关万夫莫开!
1、四种 Filter
在 ASP.Net MVC 中提供了四个 Filter(过滤器)接口实现了这种 AOP 机制:
IAuthorizationFilter、IActionFilter、IResultFilter、IExceptionFilter。
1)IAuthorizationFilter 一般用来检查当前用户是否有 Action 的执行权限,在每个 Action 被
执行前执行 OnAuthorization 方法;
2)IActionFilter 也是在每个 Action 被执行前执行 OnActionExecuting 方法,每个 Action 执行
完成后执行 OnActionExecuted 方法。和 IAuthorizationFilter 的区别是 IAuthorizationFilter 在
IActionFilter 之前执行,检查权限一般写到 IAuthorizationFilter 中;
3)IResultFilter,在每个 ActionResult 的前后执行 IResultFilter。用的很少,后面有一个应用。
4)IExceptionFilter,当 Action 执行发生未处理异常的时候执行 OnException 方法。在 ASP.net
MVC 中仍然可以使用“Global 的 Application_Error”,但是建议用 IExceptionFilter。
定义的类可以在Global中GlobalFilters.Filters.Add(new XXXFilter());的方式添加为全局的
过滤器。
2、IAuthorizationFilter 案例:只有登录后才能访问除了 LoginController 之外的 Controller。
1) 编写一个类 CheckAuthorFilter,实现 IAuthorizationFilter 接口
2) 在 Global 中注册这个 Filter:GlobalFilters.Filters.Add(new CheckAuthorFilter());
3) CheckAuthorFilter 中实现 OnAuthorization 方法。filterContext.ActionDescriptor 可以获得
Action 的信息:filterContext.ActionDescriptor.ActionName 获得要执行的 Action 的名字;
filterContext.ActionDescriptor.ControllerDescriptor.ControllerName 为要执行的 Controller
的名字;filterContext.ActionDescriptor.ControllerDescriptor.ControllerType 为要执行的
Controller 的 Type;filterContext.HttpContext 获得当前请求的 HttpContext;如果给
“ filterContext.Result ”赋值了,那么就不会再执行 要执行的 Action ,而是以
“ filterContext.Result ” 的 值 作 为 执 行 结 果 ( 注 意 如 果 是 执 行 的
filterContext.HttpContext.Response.Redirect(),那么目标 Action 还会执行的)。
4) 检查当前用户是否登录,如果没有登录则 filterContext.Result = new ContentResult()
{ Content = "没有权限" }; 或者 filterContext.Result = new RedirectResult("/Login/Index");
(最好不要 filterContext.HttpContext.Response.Redirect("/Login/Index");)
5) A 用户有一些 Action 执行权限,B 用户有另外一些 Action 的执行权限;
3、IActionFilter 案例:日志记录,记录登录用户执行的 Action 的记录,方便跟踪责任。
4、IExceptionFilter 案例:记录未捕获异常。
public class ExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
 File.AppendAllText("d:/error.log", filterContext.Exception.ToString());
 filterContext.ExceptionHandled = true;//如果有其他的 IExceptionFilter 不再执行
 filterContext.Result = new ContentResult() { Content= "error" };
}
}
然后 GlobalFilters.Filters.Add(new ExceptionFilter());
5、总结好处:一次编写,其他地方默认就执行了。可以添加多个同一个类型的全局 Filter,
按照添加的顺序执行。
6、(*)非全局 Filter:只要让实现类继承自 FilterAttribute 类,然后该实现哪个 Filter 接口就
实现哪个(四个都支持)。不添加到 GlobalFilters 中,而是把这个自定义 Attribute 添加到
Controller 类上这样就只有这个 Controller 中操作会用到这个 Filter。如果添加到 Action 方法
上,则只有这个 Action 执行的时候才会用到这个 Filter。

 Global.asax

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            GlobalFilters.Filters.Add(new CheckLoginFilter());
           
        }
    }
View Code

CheckLoginFilter

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace _04_02_登录校验Filter.Filters
{
    public class CheckLoginFilter : IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            string ctrlName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            string actionName = filterContext.ActionDescriptor.ActionName;
            if(ctrlName=="Login" && (actionName=="Index" ||actionName=="Login"))
            {
                //什么都不做
            }
            else//检查登录状态
            {
                if (filterContext.HttpContext.Session["username"] == null)
                {
                    //1.返回内容
                    //ContentResult contentResult = new ContentResult();
                    //contentResult.Content = "没有登录";
                    //如果在Filter中给FilterContext.Result 赋值了,那么将不再继续执行要执行的Filter,而是把FilterContext.Result执行,返回给用户
                    //filterContext.Result = contentResult;
                    //2.重定向
                    filterContext.Result = new RedirectResult("~/Login/Index");
                }
            }
        }
    }
}
View Code

IActionFilter  

Global.asax

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            
            GlobalFilters.Filters.Add(new LogActionFilter());
        }
View Code

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace _04_02_登录校验Filter.Filters
{
    public class LogActionFilter : IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            string ctrlName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            string actionName = filterContext.ActionDescriptor.ActionName;
            string path = filterContext.HttpContext.Server.MapPath("~/Log.txt");
            File.AppendAllText(path, "执行了" + ctrlName + "." + actionName);
        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string ctrlName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            string actionName = filterContext.ActionDescriptor.ActionName;
            string path = filterContext.HttpContext.Server.MapPath("~/Log.txt");
            File.AppendAllText(path,"将要执行"+ctrlName+"."+actionName);
        }
    }
}
View Code

 

第五章:Linq与EF入门

lambda

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NuGet
{
    class Program
    {
        static void Main(string[] args)
        {
            //lambda改造GetMax
            int[] nums = new int[] { 3, 88, 6, 9 };
            int m = GetMax(nums, (i1, i2) => i1 > i2);
            Console.WriteLine(m);

            //lambda在EF中
            List<person> list = new List<person>();
            list.Where(p => p.name=="");
            Console.ReadKey();
        }
        static T GetMax<T>(T[] objs, Func<T, T, bool> ComareFunc)
        {
            T max = objs[0];
            for (int i = 0; i < objs.Length; i++)
            {
                if (ComareFunc(objs[i], max))
                {
                    max = objs[i];
                }
            }
            return max;
        }
    }
  public  class person
    {
        public string name { get; set; }
    }
}
View Code

 集合高级扩展方法

二、 高级集合扩展方法
//学生
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public bool Gender { get; set; }
public int Salary { get; set; }
public override string ToString()
{
 return string.Format("Name={0},Age={1},Gender={2},Salary={3}",
Name, Age, Gender, Salary);
}
}
//老师
public class Teacher
{
 public Teacher()
{
 this.Students=new List<Person>();
}
public string Name { get; set; }
public List<Person> Students { get; set; }
}
var s0 =new Person { Name="tom",Age=3,Gender=true,Salary=6000};
var s1 = new Person { Name = "jerry", Age = 8, Gender = true, Salary = 5000 };
var s2 = new Person { Name = "jim", Age = 3, Gender = true, Salary = 3000 };
var s3 = new Person { Name = "lily", Age = 5, Gender = false, Salary = 9000 };
var s4 = new Person { Name = "lucy", Age = 6, Gender = false, Salary = 2000 };
var s5 = new Person { Name = "kimi", Age = 5, Gender = true, Salary = 1000 };

List<Person> list = new List<Person>();
list.Add(s0);
list.Add(s1);
list.Add(s2);
list.Add(s3);
list.Add(s4);
list.Add(s5);
Teacher t1 = new Teacher { Name="如鹏网张老师"};
t1.Students.Add(s1);
t1.Students.Add(s2);
Teacher t2 = new Teacher { Name = "如鹏网刘老师" };
t2.Students.Add(s2);
t2.Students.Add(s3);
t2.Students.Add(s5);
Teacher[] teachers = { t1,t2};
1. Any(),判断集合是否包含元素,返回值是 bool,一般比 Coun()>0 效率高。Any 还可以
指 定 条 件 表 达 式 。 bool b = list.Any(p => p.Age > 50); 等价于 bool b =
list.Where(p=>p.Age>50).Any();
2. Distinct(),剔除完全重复数据。(*)注意自定义对象的 Equals 问题:需要重写 Equals 和
GetHashCode 方法来进行内容比较。
3. 排序:升序 list.OrderBy(p=>p.Age);降序 list.OrderByDescending(p=>p.Age)。指定多个排序规
则,而不是多个 OrderBy,而是:list.OrderByDescending(p=>p.Age).ThenBy(p=>p.Salary),也支
持 ThenByDescending()。注意这些操作不会影响原始的集合数据。
4. Skip(n)跳过前 n 条数据;Take(n)获取最多 n 条数据,如果不足 n 条也不会报错。常用来
分页获取数据。list.Skip(3).Take(2)跳过前 3 条数据获取 2 条数据。
5. Except(items1)排除当前集合中在 items1 中存在的元素。用 int 数组举例。
6. Union(items1)把当前集合和 items1 中组合。用 int 数组举例。
7. Intersect(items1) 把当前集合和 items1 中取交集。用 int 数组举例。
8. 分组:
foreach(var g in list.GroupBy(p => p.Age))
{
Console.WriteLine(g.Key+":"+g.Average(p=>p.Salary));
}
9. SelectMany:把集合中每个对象的另外集合属性的值重新拼接为一个新的集合
foreach(var s in teachers.SelectMany(t => t.Students))
{
Console.WriteLine(s);//每个元素都是 Person
}
注意不会去重,如果需要去重要自己再次调用 Distinct()
10. Join
class Master

{
public long Id { get; set; }
public string Name { get; set; }
}
class Dog
{
public long Id { get; set; }
public long MasterId { get; set; }
public string Name { get; set; }
}
Master m1 = new Master { Id = 1, Name = "杨中科" };
Master m2 = new Master { Id = 2, Name = "比尔盖茨" };
Master m3 = new Master { Id = 3, Name = "周星驰" };
Master[] masters = { m1,m2,m3};
Dog d1 = new Dog { Id = 1, MasterId = 3, Name = "旺财" };
Dog d2 = new Dog { Id = 2, MasterId = 3, Name = "汪汪" };
Dog d3 = new Dog { Id = 3, MasterId = 1, Name = "京巴" };
Dog d4 = new Dog { Id = 4, MasterId = 2, Name = "泰迪" };
Dog d5 = new Dog { Id = 5, MasterId = 1, Name = "中华田园" };
Dog[] dogs = { d1, d2, d3, d4, d5 };
Join 可以实现和数据库一样的 Join 效果,对有关联关系的数据进行联合查询
下面的语句查询所有 Id=1 的狗,并且查询狗的主人的姓名。
var result = dogs.Where(d => d.Id > 1).Join(masters, d => d.MasterId, m => m.Id,
(d,m)=>new {DogName=d.Name,MasterName=m.Name});
foreach(var item in result)
{
Console.WriteLine(item.DogName+","+item.MasterName);
}
View Code

 linq

from item in items 开始,items 为待处理的集合,item 为每一项的变量名;
最后要加上 select,表示结果的数据;记得 select 一定要最后。这是刚用比较别扭的地
方。
看各种用法,不用解析:
1var r= from d in dogs
 select d.Id;
2var r = from d in dogs
 select new{d.Id,d.Name,Desc="一条狗"};
3) 排序
 var items = from d in dogs
 //orderby d.Age
 //orderby d.Age descending
 orderby d.Age,d.MasterId descending
 select d;
4) join
var r9 = from d in dogs
 join m in masters on d.MasterId equals m1.Id
 select new { DogName=d.Name,MasterName=m.Name};
注意 join 中相等不要用==,要用 equals。
写 join 的时候 linq 比“lambda” 漂亮
5) group by
var r1 = from p in list
 group p by p.Age into g
 select new { Age = g.Key, MaxSalary = g.Max(p=>p.Salary), Count = g.Count() };
4、混用
只有 Where,Select,OrderBy,GroupBy,Join 等这些能用 linq 写法,如果要用下面的
“ Max,Min,Count,Average,Sum,Any,First,FirstOrDefault,Single,SingleOrDefault,Distinct,Skip,Ta
ke 等”则还要用 lambda 的写法(因为编译后是同一个东西,所以当然可以混用)。
var r1 = from p in list
 group p by p.Age into g
 select new { Age = g.Key, MaxSalary = g.Max(p=>p.Salary), Count = g.Count() };
int c = r1.Count();
var item = r1.SingleOrDefault();

var c = (from p in list
 where p.Age>3
 select p
).Count();
 lambda 对 linq 说:论漂亮我不行,论强大你不行!
View Code

EntityFramework

 使用 EF 进行数据库开发的时候有两个东西建:建数据库(T_Persons),建模型类 (Person)。根据这两种创建的先后顺序有 EF 的三种创建方法: a) DataBase First(数据库优先):先创建数据库表,然后自动生成 EDM 文件,EDM 文件生成模型类。简单展示一下 DataBase First 的使用。 b) Model First(模型优先):先创建 Edm 文件,Edm 文件自动生成模型类和数据库; c) Code First(代码优先):程序员自己写模型类,然后自动生成数据库。没有 Edm。

 

CodeFirst(DataAnnotations方式)

1.创建表

2.通过NuGet安装EntityFramework.添加连接字符串

3.创建数据库对应模型类,主键必须Id

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _05_08_CodeFirst基本使用
{
    [Table("T_Persons")]
    public class Person
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public DateTime CreateDateTime { get; set; }
    }
}
View Code

 

4.创建继承DbContext的类

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _05_08_CodeFirst基本使用
{
    class TestDbContext:DbContext
    {
        public TestDbContext() : base("name=connStr")
        {

        }
        public DbSet<Person> Persons { get; set; }
    }
}
View Code

  EF 模型的两种配置方式 EF 中的模型类的配置有 DataAnnotations、FluentAPI 两种。

上面这种在模型类上 [Table("T_Persons")]、[Column("Name")]这种方式就叫 DataAnnotations

这种方式比较方便,但是耦合度太高,一般的类最好是 POCO(Plain Old C# Object,没 有继承什么特殊的父类,没有标注什么特殊的 Attribute,没有定义什么特殊的方法, 就是一堆普通的属性);不符合大项目开发的要求。微软推荐使用 FluentAPI 的使用方式, 因此后面主要用 FluentAPI 的使用方式。

FluentAPI 配置 T_Persons 的方式

1. 数据库中建表 T_Perons,有 Id(主键,自动增长)、Name、CreateDateTime 字段。

2. 创建 Person 类。模型类就是普通 C#类 

public class Person
{
public long Id { set; get; }
public string Name { get; set; }
public DateTime CreateDateTime { get; set; }
}

3. 创建一个 PersonConfig 类,放到 ModelConfig 文件夹下(PersonConfig、EntityConfig 这样的名字都不是必须的) 

class PersonConfig: EntityTypeConfiguration<Person>
{
public PersonConfig()
{
this.ToTable("T_Persons");//等价于[Table("T_Persons")]
}
}

4. 创建 DbContext 类

public class MyDbContext:DbContext
{
public MyDbContext():base("name=conn1")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.AddFromAssembly(
Assembly.GetExecutingAssembly());
}
public DbSet<Person> Persons { get; set; }
}

 

 下面这句话: modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly()); 代表从这句话所在的程序集加载所有的继承自 EntityTypeConfiguration 为模型配置类。 还有很多加载配置文件的做法(把配置写到 OnModelCreating 中或者把加载的代码写 死到 OnModelCreating 中),但是这种做法是最符合大项目规范的做法。 和以前唯一的不同就是:模型不需要标注 Attribute;编写一个 XXXConfig 类配置映射关系;  DbContext 中 override OnModelCreating;

5. 以后的用法和以前一样。

6. 多个表怎么办?创建多个表的实体类、Config 类,并且在 DbContext 中增加多个 DbSet 类型的属性即可。

第六章:Entity Framework 原理和状态管理

1.SQL监控

using(MYDbContext ctx=new MYDbContext())
{
ctx.Database.Log = (sql) => { Console.WriteLine(sql); };
}

EF 的查询是“延迟执行”的,只有遍历结果集的时候才执行 select 查询,ToList()内部也 是遍历结果集形成 List

 

EF 中还可以多次指定 where 来实现动态的复合检索:

//必须写成 IQueryable,如果写成 IEnumerable 就会在内存中取后续数据

IQueryable items = ctx.Persons;//为什么把 IQueryable换成 var 会编译出错

items = items.Where(p=>p.Name=="rupeng");

items = items.Where(p=>p.Id>5); 

 

每次开始执行的__MigrationHistory 等这些 SQL 语句是什么?是 DBMigration 用的,也就 是由 EF 帮我们建数据库,现在我们用不到,用下面的代码禁用: Database.SetInitializer(null); XXXDbContext 就是项目 DbContext 的类名。一般建议放到 XXXDbContext 构造函数中。 注意这里的 Database 是 System.Data.Entity 下的类,不是 DbContext 的 Database 属性。如果 写到 DbContext 中,最好用上全名,防止出错。

    public class MYDbContext : DbContext
    {
        public MYDbContext() : base("name=connStr")
        {
            System.Data.Entity.Database.SetInitializer<MYDbContext>(null);
        }
        public DbSet<Person> Persons { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly());
        }
    }

 

2.EntityFramework执行原始 SQL

不要“手里有锤子,到处都是钉子”!
在一些特殊场合,需要执行原生 SQL。
执行非查询语句,调用 DbContext 的 Database 属性的 ExecuteSqlCommand 方法,可以
通过占位符的方式传递参数:
ctx.Database.ExecuteSqlCommand("update T_Persons set Name={0},CreateDateTime=GetDate()",
"rupeng.com");
占位符的方式不是字符串拼接,经过观察生成的 SQL 语句,发现仍然是参数化查询,因此不会
有 SQL 注入漏洞。
执行查询:
var q1 = ctx.Database.SqlQuery<Item1>("select Name,Count(*) Count from T_Persons where Id>{0} and
CreateDateTime<={1} group by Name",
2, DateTime.Now); //返回值是 DbRawSqlQuery<T> 类型,也是实现了 IEnumerable 接口
foreach(var item in q1)
{
Console.WriteLine(item.Name+":"+item.Count);
}
class Item1
{
public string Name { get; set; }
public int Count { get; set; }
}
类似于 ExecuteScalar 的操作比较麻烦:
int c = ctx.Database.SqlQuery<int>("select count(*) from T_Persons").SingleOrDefault();

 

 4.EF对象状态管理

 

5、 EF 优化的一个技巧
如果查询出来的对象只是供显示使用,不会修改、删除后保存,那么可以使用
AsNoTracking()来使得查询出来的对象是 Detached 状态,这样对对象的修改也还是 Detached
状态,EF 不再跟踪这个对象状态的改变,能够提升性能。
var p1 = ctx.Persons.Where(p => p.Name == "rupeng.com").FirstOrDefault();
Console.WriteLine(ctx.Entry(p1).State);
改成:
var p1 = ctx.Persons.AsNoTracking().Where(p => p.Name == "rupeng.com").FirstOrDefault();
Console.WriteLine(ctx.Entry(p1).State);
因为 AsNoTracking()是 DbQuery 类(DbSet 的父类)的方法,所以要先在 DbSet 后调用
AsNoTracking()。

第七章:一对多,多对多配置

 FluentAPI深入讲解

1、 HasMaxLength 设定字段的最大长度

public PersonConfig()

{

this.ToTable("T_Persons");

this.Property(p => p.Name).HasMaxLength(50);//长度为 50

}

2、 (有用)字段是否可空:

this.Property(p => p.Name).IsRequired() 属性不能为空;

this.Property(p => p.Name).IsOptional() 属性可以为空;(没用的鸡肋!)

转载于:https://www.cnblogs.com/wangyinlon/p/7106630.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值