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.已分离(Detached)和未改变(Unchanged)的实体,SaveChangesAsync()忽略。
2.已添加的实体,SaveChangesAsync()插入数据库。
3.已修改的实体,SaveChangesAsync()更新到数据库。
4.已删除的实体,SaveChangesAsync()从数据库中删除。
//对象的跟踪状态
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语句,来把内存中的实体的变化更新到数据库中。
原创文章,作者:端木书台,如若转载,请注明出处:https://blog.ytso.com/277259.html