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(分配四个内存):


posted @ 2016-11-19 22:28  石shi  阅读(202)  评论(0编辑  收藏  举报