EF中逆变和协变
EF中的增删改查:
实现步骤:
1.声明一个EF的上下文。
bjhksjEntities dbContext = new bjhksjEntities();
2.声明一个实体。
HKSJ_USERS user = new HKSJ_USERS(); user.LoginName = "ssss"; user.Mail = "ssss"; user.PassWord = "ssss"; user.Plane = "ssss"; user.UserName = "ssss"; user.cardNo = "ssss"; user.phone = "ssss";
3.告诉EF对实体做什么操作。
插入: dbContext.HKSJ_USERS.Add(user);
修改和删除的时候必须指定ID: HKSJ_USERS user = new HKSJ_USERS(); user.LoginName = "ssss111--------" user.Mail = "ssss"; user.PassWord = "ssss"; user.Plane = "ssss"; user.UserName = "ssss"; user.cardNo = "ssss"; user.phone = "ssss"; user.ID = 8;
进行修改操作: dbContext.Entry<HKSJ_USERS>(user).State = System.Data.EntityState.Modified;
附加到上下文中进行管理(跟踪才能用SQL Server Profiler工具): dbContext.HKSJ_USERS.Attach(user);
修改单个属性(两种写法): dbContext.Entry<HKSJ_USERS>(user).Property<string>(u => u.LoginName).IsModified = true; dbContext.Entry<HKSJ_USERS>(user).Property("LoginName").IsModified = true;
4.让上下文把变化的实体保存到数据库中。(也是执行Sql脚本的地方)
dbContext.SaveChanges();
遇到这种错误:
实体的属性(非空、不全、超过长度)
上面的错误是没有主键。
数据已经不存在了又做了一个删除操作。或者ID没有赋值
聚簇索引和非聚簇索引的区别:
聚簇索引:索引的顺序和数据存储的顺序一致。一一对应(Guid一般不设置成聚簇索引 -----Guid无序)
非聚簇索引:(树状结构)要不通过聚簇索引找到数据库表的数据 或者自己找到数据库表的顺序。
ModelFirst生成数据库时注意:
EF在运行时改链接字符串:
dbContext.Database.Connection.ConnectionString=“”;
模型和数据库中的列进行同步:
空白处右击:
然后保存,model层就会自动生成添加列的相对属性。
或者转换所有的T4模板:
模型中添加的字段同步到数据库:
右键根据模型生成数据库:
下一步会生成一个数据库脚本.(执行)
有数据的话手动添加对应的列
Linq表达式和Sql语句的区别:
select * --1 from 表名 as u --2 where u.列名 like '%s%' --3 --执行的顺序 2,3,1 --linq from 表名 where u.列名 like '%s%' select *
EF查询:
这两个意思一样: var temp = from u in dbContext.HKSJ_USERS select u; foreach (var u in dbContext.HKSJ_USERS) { }
Linq表达式的返回类型是IQueryable<T> 继承IEnumerable<T>
out 输出参数(干涉返回值) --子类的泛型集合传给父类的泛型集合 协变 外面使用的是父类的泛型集合 编译阶段补充完整代码,本质还是内部进行转换,只不过是编译不对其报错。
in 输入参数(干涉传入的参数) --父类的泛型集合传给子类的泛型集合 逆变 (使用的时候安全 不是赋值的时候安全)
这样是不对的:
List<int> listInt = new List<int>() { 1, 2, 3 }; List<object> listObj = listInt;
错误如下:
IQueryable<HKSJ_USERS> temp = from u in dbContext.HKSJ_USERS where u.ID > 4 select u; //把子类泛型集合交给父类的泛型集合。协变。 IQueryable<object> parent = temp;
2、逆变,还是为了安全。把父类的泛型给子类的泛型对象。 Action<object> b = (target) => { Console.WriteLine(target.GetType().Name); }; Action<HKSJ_USERS> d = b; d(new HKSJ_USERS()); 赋值的时候是把父类的方法传给子类 使用的时候还是把子类的方法传给父类
Linq to EF:查询实在数据库端进行过滤
内存里面过滤:把数据库中的所有数据都查询到程序里面来之后,在进行过滤。
List集合(Array、Dictionary...)跟IQueryable接口集合的不同点。
这种写法把所有的数据加载到内存中去:(Linq to Object) 条件在内存中进行过滤 数据库中查询所有。(.ToLis立即加载到内存中)本地集合
var demoList = from u in dbContext.HKSJ_USERS.ToList() where u.ID > 4 select u; foreach (var hksjUsers in demoList) { }
对此句代码进行分析:
IQueryable<HKSJ_USERS> temp = from u in dbContext.HKSJ_USERS where u.ID > 4 select u;
初始化了一下IQueryable接口里面的三个参数:(离线集合)
1.Linq 表达式转换成Expression类型
2.给 Type ElementType赋值
3.给IQueryProvider Provider赋值
当用到IQueryable接口集合数据的时候,provider解析 Expression 然后获取相应的数据,进行遍历执行
内部的代码:
Linq的一个工具:(LINQPad)
最后来一张图:本地集合List(分配四个内存):