EF Core Linq(252)

EF默认情况下对数据的访问都是启用模型跟踪

使用AsNoTracking方法查询返回无变动跟踪的Province的DbSet,由于是无变动跟踪,所以对返回的Province集中数据的任何修改,在SaveChanges()时,都不会提交到数据库中

  • 无跟踪查询而已,也就是说查询出来的对象不能直接做修改。所以,我们在做数据集合查询显示,而又不需要对集合修改并更新到数据库的时候,一定不要忘记加上AsNoTracking。
1
2
3
4
5
6
7
8
9
10
11
12
using (var context = new MyDbContext())
{
var data = context.Orders
.Include(c => c.OrderLines)
.Select(c => new { OrderObj = c, Lines = c.OrderLines})
.AsNoTracking()//除非去掉这句不然不会更新
.FirstOrDefault();
data.OrderObj.Number = "#ABC123";
context.SaveChanges();
}
  • 如果查询过程做了select映射就不需要加AsNoTracking。如:db.Students.Where(t=>t.Name.Contains(“张三”)).select(t=>new (t.Name,t.Age)).ToList();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//导出部分属性列,提高效率
.AsNoTracking()
.Select(item =>
new ProductViewModel
{
Product = item,
NoOfProducts = item.Comments.Count
}).ToListAsync());
//同理
var list = context.Bloggers
.Include(x => x.Posts)
.ToList();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//更新单列
//这个方法需要注意一点,就是禁止多个跟踪。假如前面用track方式`where`选出了一些对象,由于这些对象被跟踪了,再用这个方法`attach`添加跟踪就会异常。除非用同一个对象更新
using (TestDBContext testDBContext = new TestDBContext())
{
Person person = new Person() { Code = "A" ,Name="Tom"};//列Code是Key,声明Key属性列Code的值,及要修改的列Name的值
testDBContext.Attach(person);//告诉EF Core开始跟踪person实体的更改,因为调用DbContext.Attach方法后,EF Core会将person实体的State值(可以通过testDBContext.Entry(person).State查看到)更改回EntityState.Unchanged,所以这里testDBContext.Attach(person)一定要放在下面一行testDBContext.Entry(person).
Property(p => p.Name).IsModified = true的前面,否者后面的testDBContext.SaveChanges方法调用后,数据库不会被更新
testDBContext.Entry(person).Property(p => p.Name).IsModified = true;//告诉EF Core实体person的Name属性已经更改。将testDBContext.Entry(person).Property(p => p.Name).IsModified设置为true后,也会将person实体的State值(可以通过testDBContext.Entry(person).State查看到)更改为EntityState.Modified,这样就保证了下面SaveChanges的时候会将person实体的Name属性值Update到数据库中。
testDBContext.SaveChanges();
}
context.Attach(person);
context.Entry(person).Property("Name").IsModified = true;
context.SaveChanges();
//更新还有个mysql坑,那就是int主键默认是0。因为主键ID默认是不赋值的,只给其他项目赋值了 id是int类型,int类型如果不允许为空那么会被默认为0,所以插入第二条数据时,数据库中已经有了主键为0的数据
//modelBuilder.Entity<Person>(entity =>
//{
// entity.Property(e => e.Id).ValueGeneratedOnAdd();//这句会用到的
// entity.HasKey(e => e.Code);//声明列Code是实体的Key属性
//});

自定义标量函数

Entity Framework Core 有一个重要特性就是自定义标量函数。
自定义标量函数可以将数据库中的标量函数映射到类中的方法,并且在使用 LINQ 查询时会用到

我看例子他们还可以映射数据的函数Average Max Min
···

[DbFunction(FUNCTIONnAME=”sdf”,Schema=”dd”)]
public static string my()
{}

//调用
public int GetNextValId(string value)
{
return Context.DbpTask.Select(x => IngestTaskDBContext.next_val(value)).FirstOrDefault();
}
···

显式编译查询

一般的NoTracking()查询,此时要经过编译翻译阶段最终返回实际结果,比如在Web网站上这样的请求很频繁,此时将严重影响响应速度导致页面加载数据过慢。

1
2
3
4
5
6
7
8
9
static async Task<Blog> GetBlogAsync(EFCoreDbContext context, int id)
{
Func<EFCoreDbContext, int, Task<Blog>> blog = EF.CompileAsyncQuery((EFCoreDbContext context, int Id) =>
context.Blogs.Include(c => c.Posts)
.Where(c => c.Id == Id)
.FirstOrDefault());
return await blog(context, id);
}
//提前把查询编译好,再直接返回查询结果的方式

延时加载技术

用的时候才会加载

// //