//错误,因为上下文在方法执行完成就销毁了 IQueryable<Book> QueryBooks() { using TestDbContext ctx = new TestDbContext(); return ctx.Books.Where(b => b.Id > 5); } //正确做法 IEnumerable<Book> QueryBooks() { using (TestDbContext ctx = new TestDbContext()) { return ctx.Books.Where(b => b.Id > 5).ToArray(); } }
场景2:IQueryable嵌套
DataReader方式,有些数据库不支持多个DataReader同时执行
1 2 3 4 5 6 7 8 9 10
//错误,有两个DataReader var books = ctx.Books.Where(b=>b.Id>1); foreach(var b in books) { foreach(var a in ctx.Authors) { Console.WriteLine(a.Id); } } //可以将某个IQueryable使用ToList()加载到内存中来解决
using TestDbContext ctx = new TestDbContext(); int year = int.Parse(Console.ReadLine()); //参数是同样是FormattableString类型,会自动把{year}翻译为@p0 IQueryable<Book> books = ctx.Books.FromSqlInterpolated(@$"select * from T_Books where DatePart(year,PubTime)>{year} order by newid()"); foreach (Book b in books) { Console.WriteLine(b.Title); } //返回值是IQueryable类型,可以复用
FromSqlInterpolated的局限下:
SQL查询必须返回实体类型对应数据库表的所有列
查询结果集中的列明必须与属性映射到列明匹配
只能进行单表查询,不能使用过Join进行关联查询,但是可以在查询后面使用Include方法进行查询
实体类的跟踪
EF Core采用“快照更改跟踪”实现实体类改变的检测,当执行SaveChanges方法的时候,把存储在快照中的值与实体类的当前值进行比较,已确定哪些属性被更改。