.NETEFCore之增删改查
1. 连接数据库
通过依赖注⼊配置应⽤程序,通过startup类的ConfigureService⽅法中的AddDbContext将EFCore添加到依赖注⼊容器
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext(
options => options.UseMySql(Configuration["DbConfig:Mysql:ConnectionString"]);
}
将名为 OpenDbContext的 DbContext ⼦类注册到依赖注⼊容器的Scope⽣命周期。上下⽂配置为使⽤MySQL数据库提供程序,并从配置中读取数据库连接字符串。
OpenDbContext类必须公开具有 DbContextOptions参数的公共构造函数。这是将 AddDbContext 的上下⽂配置传递到DbContext 的⽅式。
public class OpenDbContext : DbContext
{
public OpenDbContext(DbContextOptions options) : base(options)
{
}
public DbSet Users { get; set; }
public DbSet Scores { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//另⼀种配置连接数据库的⽅式
//optionsBuilder.UseMySql("连接数据库", ServerVersion.AutoDetect("连接数据库字符串"));
//显⽰敏感数据⽇志
optionsBuilder.EnableSensitiveDataLogging(true);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//属性配置
//modelBuilder.Entity()perty(t => t.Account).IsRequired().HasMaxLength(20).HasComment("帐号");
//种⼦数据设置
//modelBuilder.Entity().HasData(new User { Account="种⼦"});
//批量添加etc的操作
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
base.OnModelCreating(modelBuilder);
}
}
然后将OpenDbContext通过构造函数注⼊的⽅式注⼊到应⽤程序的控制器或者其他服务中使⽤。
关于连接数据库可以参考另⼀个⽂章:.Net之⽣成全流程
2. 操作数据库
context.Database.EnsureDeleted();//删除数据库,如果存在,如果没有权限,则引发异常
context.Database.EnsureCreated();//如果数据库不存在,创建数据库并初始化数据库架构,如果存在任何表,则不会初始化架构
context.Database.Migrate();//根据迁移⽂件,迁移数据库
bean标签list注入内部类 3. 查询操作3.1 基础查询
db.Set().ToList();
//查询表达式
var account = (from u in _context.Users
where u.Id == id
select u.Account
).ToList();
//查询单个
_context.Movie.FirstOrDefaultAsync(m => m.ID == id);
_context.Movie.FindAsync(id);
//查询指定列
_context.Set().AsNoTracking().Where(t=>t.Id=="11").Select(t => new { t.Account, t.PassWord }).FirstOrDefaultAsync();
// 预先加载查询
var blogs = context.Blogs.Include(blog => blog.Posts).ToList();
// 包含多个层级的查询
var blogs = context.Blogs.Include(blog => blog.Posts).ThenInclude(post => post.Author).ToList();
SingleOrDefaultAsync 与FirstOrDefaultAsync
如果有多个实体符合筛选部分, SingleOrDefaultAsync 将引发异常。
如果有多个实体符合筛选部分, FirstOrDefaultAsync 不引发异常。
FindAsync
在⼤部分基架代码中,FindAsync 可⽤于替代 FirstOrDefaultAsync ,查具有主键 (PK) 的实体。如果具有 PK 的实体正在由上下⽂跟踪,会返回该实体且不向 DB 发出请求。
3.2 跟踪和⾮跟踪查询
跟踪⾏为决定了EFCore是否将有些实体的信息保存在其更改更跟踪器中。如果已跟踪某个实体,则该实体中检测到的任何更改都会在SaveChanges()时候保存到数据库,
不跟踪没有主键的实体类型。
# 跟踪查询
_context.Set().ToListAsync();
# ⾮跟踪查询
_context.Set().AsNoTracking().ToListAsync();
默认是跟踪查询
3.3 条件查询3.3.1 不⽀持异步⽅案
Func express = x => true;
if (!string.IsNullOrWhiteSpace(dto.Data))
{
express = x => xle == dto.Data;
scratch编程游戏100例 }
string userid = "";
if (!string.IsNullOrWhiteSpace(userid))
{
express = x => x.UserId == userid;
}
var bbb = _dbContext.Set().Where(express).FirstOrDefault();
3.3.2 ⽀持异步⽅案
Expression> express = x => true;
if (!string.IsNullOrWhiteSpace(dto.Data))
{
express = x => xle == dto.Data;
}
var bbb = await _dbContext.Set().Where(express).ToListAsync();
3.4 原⽣SQL查询
可使⽤ FromSqlRaw 扩展⽅法基于原始 SQL 查询开始 LINQ 查询。FromSqlRaw 只能在直接位于 DbSet<> 上的查询根上使⽤。
3.4.1 基本原⽣SQL查询
var blogs = context.Blogs
.FromSqlRaw("select * from user")
.ToList();
// 执⾏存储过程
var blogs = context.Blogs
.FromSqlRaw("EXECUTE dbo.GetMostPopularBlogs")
2.x⾥⾯使⽤FromSql,在
3.x⾥⾯使⽤FromSqlRow⽅法
mysql菜鸟教程增删改查autojs能和vue一起写吗 3.4.2 参数化查询3.4.2.1 SQL注⼊
⾸先我们编写⼀个简单的SQL注⼊⽰例,⽐如就注⼊我们根据ID查询的语句,输⼊ID为:ididid' or '1'='1
var strSql = string.Format("select * from user where Id='{0}'", "ididid' or '1'='1");
var query = await _context.Set().FromSqlRaw(strSql).ToListAsync();
Console.WriteLine(JsonConvert.SerializeObject(query));
⽣成语句
select * from user where Id='ididid' or '1'='1'
[{"Account":"张三","PassWord":"123456","CreateTime":"2021-05-
20T22:53:44.778101","IsValid":false,"Id":"1395392302788120576"},{"Account":"李四","PassWord":"123456","CreateTime":"2021-05-20T22:53:44.849376","IsValid":false,"Id":"1395392303090110464"}, {"Account":"王五","PassWord":"123456","CreateTime":"2021-05-
20T22:53:44.849425","IsValid":false,"Id":"1395392303090110467"}]
3.4.2.2 FromSqlRaw参数化
通过参数化查询,防⽌SQL注⼊问题
//sql语句参数化查询,防⽌SQL注⼊
var strSql = "select * from user where Id=@id";
var parameter = new MySqlParameter[] {
new MySqlParameter("@id","1395392302788120576"),
};
var query = await _context.Set().FromSqlRaw(strSql, parameter).ToListAsync();
或者
var strSql = "select * from user where Id={0}";
var query = await _context.Set().FromSqlRaw(strSql, "1395392302788120576").ToListAsync();
Console.WriteLine(JsonConvert.SerializeObject(query));
eclipse下载及安装步骤 // ⽣成SQL
select * from user where Id=@p0
[{"Account":"张三","PassWord":"123456","CreateTime":"2021-05-
20T22:53:44.778101","IsValid":false,"Id":"1395392302788120576"}]
通过占位符形式提供额外的参数,看上去类似于String.Format语法,但是提供的值包装在DbParameter中。可以防⽌SQL注⼊
java在哪里学 3.4.2.3 FromSqlInterpolated参数化
FromSqlInterpolated 类似于 FromSqlRaw,但你可以借助它使⽤字符串内插语法。与 FromSqlRaw ⼀样,FromSqlInterpolated 只能在查询根上使⽤,并且都可以防⽌SQL注⼊。
var query = await _context.Set().FromSqlInterpolated($"select * from user where Id= {"1395392302788120576"}").ToListAsync();
Console.WriteLine(JsonConvert.SerializeObject(query));
select * from user where Id=@p0
[{"Account":"张三","PassWord":"123456","CreateTime":"2021-05-
20T22:53:44.778101","IsValid":false,"Id":"1395392302788120576"}]
3.4.3 限制SQL查询必须返回实体类型的所有属性的数据。结果集中的列明必须与属性映射到的列名称匹配。SQL查询不能包含关联数据, 但是,在许多情况下你可以在查询后⾯紧跟着使⽤ Include ⽅法以返回关联数据(请参阅包含关联数据)。
参考⽂档:docs.microsoft/zh-cn/ef/core/querying/raw-sql
3.5 复杂查询
数据如下:
⽤户表(user)
image.png
⽤户成绩表(score)
image.png
描述:包含三个⽤户,其中两个⽤户在成绩表都有语⽂和数学的数据。
3.5.1 内连接
内连接:分为隐式内连接和显式内连接(写法不同,结果相同)
3.5.1.1 Linq查询表达式显式内连接:join-in-on拼接
var list = (from u in _context.Users
join sc in _context.Scores on u.Id equals sc.UserId
where sc.CourseName == "语⽂"
select new
{
u.Account,
u.PassWord,
sc.CourseName,
sc.Grade
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论