关于使用ef框架所踩的坑

ef框架使用linq和sql语言来进行查询数据库,
但进行非映射对象查询使用sql语句来进行查询时.例如:

using (var item= new BloggingContext())
{
   var array= context.Database.SqlQuery<string>(
                       "SELECT Namevalue FROM dbo.XXX").ToList();
}

注意啊!!! 这里的映射的类是Database类,就算SQL是进行非查询直接进行增删改的操作也是用这个类

关于使用SelectMany的注意点

当进行多表查询时可以用selectMany,它可以不用在代码中不体现关系但必须在数据库中体现出表和表之间的关系,例子如下:

 var date = from c in context.CategoryDBs
            from p in c.ProductDBs
            select new {CategoryName=c.Name,ProcuctName=p.Name};
 foreach (var p in date) {
    Console.WriteLine("分类:{0}\t{1}",p.CategoryName,p.ProcuctName);
 }

例子中直接用c拿到productdbs,这个在数据库表中已经做好了表的关系,只是在代码中省略联系由ef自行管理
上面的例子中用了两个from语句来,可以用方法来进行代替

 var date = context.CategoryDBs.SelectMany(c=>c.ProductDBs.Select(p=>new { CategoryName = c.Name, ProcuctName = p.Name }));

用方法的话更加清楚的体现其逻辑
补充一下linq在c#很香哦,linq可应用于对象,关系数据库,xml的一致查询中,这种比js更香

                int[] array = { 45454,4444,8888,2222,444,666 };
                array= array.Select(a=>a*2).ToArray();
                foreach (var a in array)
                {
                    Console.WriteLine(a);
                }
where的相关

当判断语句过于复杂可以用方法来进行实现,但是必须是数据集合,因为在使用方法时是直接用方法引入,如果不用数据集会导致报错

var date = from s in context.StudentDBs.ToList()
                           where CheckStudent(s.ClassId,s.CourseId) 
                           select s.Name;
                foreach (string a in date)
                {
                    Console.WriteLine(a);
                }

还可以使用OfType()来快速筛选数据类型

ArrayList array = new ArrayList { "Mon","Tue","Wed",1,2,3,5};
                 var b  =array.OfType<int>().ToArray();
                foreach ( int item in b)
                {
                    Console.WriteLine(item);
                }
排序

orderBy 升序排序 orderby descending 降序排序 thenby二次升序排序 thenbydescending 二次降序排序 reverse反转集合中的对象排序
用下列例子说明 orderby xx desceding,他两之间是存在条件的

var products = from s in context.ProductDBs
                                orderby s.Price descending
                                select s;

使用方法就是

 var products = context.ProductDBs.OrderByDescending(p=>p.Price)                       

如果不加decending的话就是升序的
排序后再进行排序
下面是排序后再进行升序

 var products = context.ProductDBs.OrderBy(p => p.Name).ThenBy(p=>p.Price);

下面是排序后再进行降序

var products = context.ProductDBs.OrderBy(p => p.Name).ThenByDescending(p=>p.Price);

在linq中没有直接关键字thenby


group x up b

这个其实就是一种值分组 x为分组的元素 b为分组的依据,后面这个依据也是根据值来进行划分的

var products = from p in context.StudentDBs
                               group p by p.ClassId into o 
                               orderby o.Key
                               select o;
                foreach (var a in products)
                {
                    foreach (var b in a)
                    {
                        Console.WriteLine(b.Name+"------"+b.ClassId);
                    }
                    Console.WriteLine("----------------------");
                }

分组后的products是一个集合a,这个集合里面的元素是键值对,键值对中,值也是集合,这个键就是分组的依据值


ToDictionary

生成键值对的形式,该方法里面要设置键的值

Dictionary<string, string> booksDictionary = listBooks.ToDictionary(key=>"book-"+(index++).ToString())

如果要输出键值对的话个人建议采用集合的方式,可以使用转化类的方式来生成集合更加方便


ToLookup

这个可以根据重复的键对应的值集中起来形成新的值,键还是原来的键,就是一对多的关系,这种的话很用,对于某些情况

var products = context.ProductDBs.ToLookup(key=>key.CategoryId);
                foreach (IGrouping<int,ProductDB> g in products )
                {
                    Console.WriteLine("\n{0}",g.Key);
                    foreach (ProductDB p in g)
                    {
                        Console.WriteLine(p.Name);
                    }
                }
Entity SQL

这玩意类似sql

string sql = "select * from ProductDB as a order by a.Price desc";//这行就是
                var date=(context.Database.SqlQuery<ProductDB>(sql));

如果有参数可以使用SqlParameter来包装,如下:

  var date=(context.Database.SqlQuery<ProductDB>(sql,new SqlParameter("CategoryId",1)));
Console.WriteLine(date);
聚合函数

aggregate 执行自定义集合的集合运算
average 计算几何中所有值的平均值
count 计算集合中元素个数
longCount 计算大型集合中元素的项数
max 获取集合中的最大值
min 获取集合中的最小值
sum 计算集合中所有值的总和

以average为例子:

List<double> list = new List<double> {1,2,4,3,5};
double averageValue = list.Average()
double averageValue1 = list.Average(x=>x*10);//能够对每项元素进行操作,可以选择不使用的哦
Console.WriteLine(averageValue);

特殊说明
aggregate函数对集合中元素进行操作

 string a= list.Aggregate((bword,aword)=> { return bword+"\n@"+aword+"@"; });

聚合函数的含义是在于最后的值,对应上面的例子最后的值是bword,明白这个就不会纠结了
设置操作
设置操作类似集合操作,对两个集合中的元素进行对比产生关联的结果,此类型的运算分为4种
Distinct 从一个集合中去除重复元素 典型的集合
Except 比较两个集合,取出只在集合中出现一次的元素 不就是两个集合的并集减去交集嘛
interserct 对比两个集合取出重复的元素 交集
union 对比两个集合,将其中的数据全程取出 并集

现在问题是知道两个集合,但是我想要求其中一个集合除两个集合交集的集合?
其实很简单,知道两个集合的交集,取出来,它也是集合B,然后和那个目标集合A进行上面的except运算就可以得出集合C,这个集合C就是最终的结果

老弟别紧张,这个不就是高中的经典的两个集合的关系吗,将上面内聚可以思考集合元素的运算,这个设置不就是集合间的运算吗
产生操作
产生操作用来创建一组新的数据集合序列,简单点就是产生新的数据集合
以前的集合中的元素的内聚元素,集合运算,都是基于现有的集合,这个就是基于产生集合

DefaultlfEmpty 以默认值置换空集合内容
Empty 返回一个空的集合
Range 创建包含序列值的集合
Repeat 创建包含重复值的集合

List<string> list=  Enumerable.Empty<string>()
List<int> list=  Enumerable.Range(1,10).ToList();

本人很好奇查询一下这个Enumerable这个类:官方为
提供一组用于查询实现 IEnumerable 的对象的 static方法。
IEnumerable不就是linq中查询结果的返回类型吗?查看命名空间
System.Linq
哈哈哈,api文档还是得翻翻
计数运算
可以简单认为是集合与元素的关系
计数运算返回一个true或false的布尔值,表示序列集合中的元素是否符合指定条件值
all 指出序列中的所有元素是否符合条件值
any指出序列中是否存在一个元素符合条件值
contains 指出序列中是否包含指定元素

List<int> list = new List<int> { 1, 2, 3, 4, 255, 666 };
Console.WriteLine(list.Contains(4));

截取运算
简单一点说就对数据集合的筛选
skip就是跳,skipwhile就是有条件的条,take就是拿,takewile就是有条件的拿

 IEnumerable<int> enu= list.Skip(5);
                IEnumerable<int> enus= list.SkipWhile(x=>x<=3);
                 IEnumerable<int> e= list.Take(4);
                IEnumerable<int> en = list.TakeWhile(x=>x>5.2);

元素操作
下面的操作都是方法,方法,方法,方法
first 获得集合中的第一个元素
last 获得集合中的最后一个元素
elementAt 获得自定索引的元素 简称 X[index]

 List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 255, 666 };
                //list.Reverse();
                int a = list.First();
                int e = list.Last();
                int en= list.ElementAt(3);
                List<int> listOther = new List<int> { 188};
                Console.WriteLine(a);
                Console.WriteLine(e);
                Console.WriteLine(en);

总结集合中元素的操作:

  1. 如果是要对每个元素上去操作可以用select可以使用方法嵌套,类型强转,也可以使用内聚函数里面的自定义函数aggregate 对每个元素进行操作。
  2. 如果是想对某些特定元素的集合操作的话可以先对旧集合a使用skipwhile或者是takewhile,然后对再对这些符合条件集合逐个进行操作。
  3. 如果要对个别特定元素操作的话可以使用First,Last,Single等方法,老铁看清楚是方法,只有是数据集合体都可以

关于空的code first的坑

当使用空的code first创建结构时会出现,如果在开发过程中再次修改实体数据结构,或者创建实体时会破坏数据库上下文,这时运行程序会出现异常,说映射体已经发生改变了,而在ef框架中要保持实体数据上下文和数据库一致的话就只能用数据迁移。。。说句实话很不方便。。开启数据源,添加一个备份数据文件(会将输入导入到一个新的数据表中),运行迁移,,
语句如下:

Enable-migrations   

开启迁移服务 老铁没看错是开启服务,不是执行功能哦

Add-migration XXX 

添加迁移文件
这个添加迁移文件会有提示,需要再敲一遍

Update-Datebase

开始执行迁移


注释

Table—数据表
在类名称上方设置注释[Table(tablename)] 如果需要注解说要生成什么样的表

key/column------键与字段
通过标识的[key],避开惯例原则指定主键字段,通过[column(xxx)]指定映射的字段

Required
如果属性是必要值,可以设置[Required]强制要求此属性包含数据

MaxLength,MinLength
如果指定字段长度,可以设置MaxLength与MinLength属性

NotMapped
对于某些基于程序运算需求而建立的属性,在数据表中并没有映射的字段,可以设置notmapped

DatabaseGenerated
对于某些字段,我们可能希望数据库自行管理或运算,例如自动计数的id字段
[DatabaseGenerated(DatabaseGeneratedOption.option)]


Fluent API

在OnModelCreating重写其方,如下:
ModelBuilder.Entity.<映射文件>().totable(“xxx”);其中xxx为表格名称

类型映射
modelbuilder.ignore();xxx为映射类

属性映射
避免某个属性被映射
modelBuilder.Entity().ignore(p=>p.sprice)
指定映射字段
modelBuilder.Entity().property(p=>p.xxx).hascolumnName(“bbbb”),其中xxx为类中属性,指定生成表bbbb

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值