EF Core 中的异步方法

1.SaveChanges(), SaveChangesAsync()

2.异步方法大部分是定义在Microsoft.EntityFrameworkCore这个命名空间下的EntityFrameworkCoreQueryableExtensions等类中的扩展方法,记得using
3.一些异步方法

TestDbContext ctx = new TestDbContext();

await ctx.SaveChangesAsync();
await ctx.AddAsync(new User { Name ="1" });

await ctx.AddRangeAsync(new[] { new User { Name ="2" } });

await ctx.Users.AnyAsync(u=>u.Id == 5);

//之后看看
await ctx.Users.AllAsync(u=>u.Id == 5);

await ctx.Users.AverageAsync(u => u.Id);

await ctx.Users.CountAsync(u=>u.Id == 5);

await ctx.Users.CountAsync();

await ctx.Users.FirstAsync();

await ctx.Users.ForEachAsync(u => u.Name = u.Name + "1");

await ctx.Users.LongCountAsync();

await ctx.Users.SingleAsync();

await ctx.Users.SingleOrDefaultAsync();

await ctx.Users.SumAsync(u=>u.Id);


//异步循环1 一般不这样做
await foreach (var l in ctx.Leaves.AsAsyncEnumerable())
{
    Console.WriteLine(l.Remarks);
}

//异步循环2 一般不这样做
foreach (var l in await ctx.Leaves.ToListAsync())
{
    Console.WriteLine(l.Remarks);
}
EF Core 执行非查询原生sql语句
--将查询出来的数据插入数据库
insert into T_Articles(Title,Message,Price)
select Title,'新闻正文xxx',Price
from T_Articles
where Price>=10
using (TestDbContext ctx2 = new TestDbContext())
{
    string tj1 = "10";
    //执行非查询原生sql语句
    await ctx2.Database.ExecuteSqlInterpolatedAsync(@$"insert into T_Articles(Title,Message,Price)
                                                    select Title,'新闻正文xxx',Price
                                                    from T_Articles
                                                    where Price>={tj1}");
}
执行实体相关的查询原生SQL语句
   //执行实体相关的查询原生SQL语句
     var users = ctx2.Users.FromSqlInterpolated(@$"select * from T_Users where Name like '%杨%'");
    //可以只写必须要使用原生sql的部分 其他的对此的数据的操作可以用EF Core来完成
    //用Guid来无序排序
    foreach (var user in users.OrderBy(u => Guid.NewGuid()))
    {
        Console.WriteLine(user.Name);
    }

查询出来的要与实体列一一对应

只能单表查询,不能使用join查询,但是后续可以在查询结果后面Incluede()来,进行关联数据的获取。

执行原生sql语句 调用ADO.Net
 //执行原生sql语句 调用Ado.Net api
    //拿到Context对应的底层的 Connection
    DbConnection coon = ctx2.Database.GetDbConnection();
    if (coon.State != System.Data.ConnectionState.Open)
    { 
        await coon.OpenAsync(); 
    }

    using (var cmd = coon.CreateCommand())
    {
        cmd.CommandText = @$"select Name,count(*) from T_Users";
        using (var reader = await cmd.ExecuteReaderAsync())
        {
            while (await reader.ReadAsync()) 
            {
                var name = reader.GetString(0);
                var count = reader.GetInt32(1);
                Console.WriteLine($"{name}:{count}");
            }
        }
    }
总结

一般的Linq操作即可,尽量不要写原生sql

1.非查询sql用await ctx2.Database.ExecuteSqlInterpolatedAsync();

2.针对实体的sql查询用ctx2.Users.FromSqlInterpolated();

3.复杂sql查询用ADO.Net的方式获取Dapper等。

EF Core 如何判断数据发生了变化
//只要一个实体对象和DbContext发生任何的关系(查询,add,和与DbContext有关系的其他对象产生关系)
//都默认会被DbContext跟踪   
User user1 = await ctx.Users.FirstAsync();//EF Core存储了一个副本(快照)
    user1.Name = "2222";
 User user2 = new User();//这状态是Detached
    await ctx.SaveChangesAsync();//此时 对象与快照的值对比 发生改变则修改

实体的状态1

总结:

1.已分离(Detached)和未改变(Unchanged)的实体,SaveChangesAsync()忽略。

2.已添加的实体,SaveChangesAsync()插入数据库。

3.已修改的实体,SaveChangesAsync()更新到数据库。

4.已删除的实体,SaveChangesAsync()从数据库中删除。

查看EF Core快照跟踪信息2

//对象的跟踪状态
using TestDbContext ctx = new TestDbContext();
Book[] books = ctx.Books.Take(3).ToArray();
Book b1 = books[0];
Book b2 = books[1];
Book b3 = books[2];
Book b4 = new Book { Title = "零基础趣学C语言", AuthorName = "老杨" };
Book b5 = new Book { Title = "百年孤独", AuthorName = "马尔克斯" };
b1.Title = "abc";
ctx.Remove(b3);
ctx.Add(b4);
EntityEntry entry1 = ctx.Entry(b1);
EntityEntry entry2 = ctx.Entry(b2);
EntityEntry entry3 = ctx.Entry(b3);
EntityEntry entry4 = ctx.Entry(b4);
EntityEntry entry5 = ctx.Entry(b5);
Console.WriteLine("b1.State:" + entry1.State);
Console.WriteLine("b1.DebugView:" + entry1.DebugView.LongView);
Console.WriteLine("b2.State:" + entry2.State);
Console.WriteLine("b3.State:" + entry3.State);
Console.WriteLine("b4.State:" + entry4.State);
Console.WriteLine("b5.State:" + entry5.State);
总结

DbContext会根据跟踪的实体的状态,在调用SaveChangesAsync的时候,根据实体状态的不同,生成Update,Delete,Insert等SQL语句,来把内存中的实体的变化更新到数据库中。