学习参考:
1. .NET 6教程,.Net Core 2022视频教程,杨中科主讲— 以及资料参考
2. 官方文档EF core
常用的语句
3..netmvc
https://www.cnblogs.com/1016391912pm/p/12024671.html
https://github.com/dotnet/EntityFramework.Docs/tree/main/samples/core/Querying/Overview
第一个EFCore应用
https://docs.microsoft.com/zh-cn/ef/core/modeling/entity-types?tabs=fluent-api
//添加包
Microsoft.EntityFrameworkCore.Sqlite
Pomelo.EntityFrameworkCore.MySql
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools
Add-Migration InitialCreate//实现迁移
Update-database//生成数据库
Update-Database InitialCreate
Remove-migration//删除最后一次的迁移脚本
Script-Migration//生成迁移SQL代码
Script-Migration D F//生成版本D到版本F的SQL脚本
Script-Migration D//生成版本D到最新版本的SQL脚本:
dotnet add package Microsoft.EntityFrameworkCore.Design//添加 EF Core 工具所需的包。
dotnet tool install --global dotnet-ef//将安装 dotnet ef,用于创建迁移和基架的工具。
dotnet ef migrations add InitialCreate --context PizzaContext//创建数据库的迁移
dotnet ef database update --context PizzaContext//将应用迁移生成数据库。
builder.Services.AddSqlite<PizzaContext>("Data Source=ContosoPizza.db");
(Object Relational Mapping关系对象映射)
让开发者用对象操作的形式操作关系数据库。
.net 常用的orm:EF core、Dapper、SqlSugar、FreeSql
1、Entity Framework Core(EF Core)是微软官方的ORM框架。优点:功能强大、官方支持、生产效率高、力求屏蔽底层数据库差异;缺点:复杂、上手门槛高、不熟悉EFCore的话可能会进坑。
2、Dapper。优点:简单,N分钟即可上手,行为可预期性强;缺点:生产效率低,需要处理底层数据库差异。
3、EF Core是模型驱动(Model-Driven)的开发思想,Dapper是数据库驱动(DataBase-Driven)的开发思想的。没有优劣,只有比较。
4、性能: Dapper等≠性能高;EF Core≠性能差。
5、EF Core是官方推荐、推进的框架,尽量屏蔽底层数据库差异,.NET开发者必须熟悉,根据的项目情况再决定用哪个。
对于后台系统、信息系统等和数据库相关开发工作量大的系统,且团队比较稳定,用EF Core;对于互联网系统等数据库相关工作量不大的系统,或者团队不稳定,用Dapper。
EF中的上下文(DbContext)简介
DbContext是实体类和数据库之间的桥梁,DbContext主要负责与数据交互,主要作用:
1、DbContext包含所有的实体映射到数据库表的实体集(DbSet < TEntity >)。
2、DbContext 将LINQ-to-Entities查询转换为SQL查询并将其发到数据库。
3、更改跟踪: 它跟踪每个实体从数据库中查询出来后发生的修改变化。
4、持久化数据: 它也基于实体状态执行插入、更新和删除操作到数据库中
DbContext类是EntityFramework (简称 EF)中的一个类,可以理解为一个数据库对象的实例。在 EF中,无需手动的拼接 SQL 语句对数据库进行增删改查,而是通过 DbContext 来进行相应操作。
https://docs.microsoft.com/zh-cn/ef/core/modeling/entity-types?tabs=fluent-api
1、视图与实体类映射:modelBuilder.Entity<Blog>().ToView("blogsView");
2、排除属性映射:
modelBuilder.Entity<Blog>().Ignore(b => b. Name2);
3、配置列名:
modelBuilder.Entity<Blog>().Property(b =>b.BlogId).HasColumnName("blog_id");
4、配置列数据类型:
builder.Property(e => e.Title) .HasColumnType("varchar(200)")
5、配置主键
默认把名字为Id或者“实体类型+Id“的属性作为主键,可以用HasKey()来配置其他属性作为主键。modelBuilder.Entity<Student>().HasKey(c => c.Number);
支持复合主键,但是不建议使用。
6、生成列的值
modelBuilder.Entity<Student>().Property(b => b.Number).ValueGeneratedOnAdd();
7、可以用HasDefaultValue()为属性设定默认值
modelBuilder.Entity<Student>().Property(b => b.Age).HasDefaultValue(6);
8、索引
modelBuilder.Entity<Blog>().HasIndex(b => b.Url);
复合索引
modelBuilder.Entity<Person>().HasIndex(p => new { p.FirstName, p.LastName });
唯一索引:IsUnique();聚集索引:IsClustered()
9... 用EF Core太多高级特性的时候谨慎,尽量不要和业务逻辑混合在一起,以免“不能自拔”。比如Ignore、Shadow、Table Splitting等……
## ef core
//模型声明Blogs、AuditEntry、Post
internal class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AuditEntry>();
}
}
# 从模型中排除类型
[NotMapped]
public class BlogMetadata
{
public int BlogId { get; set; }
public string Url { get; set; }
[NotMapped]//排除属性
public DateTime LoadedFromDatabase { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Ignore<BlogMetadata>();
// modelBuilder.Entity()
// .Ignore(b => b.LoadedFromDatabase);
}
# 表名称、表架构、表注释
按照约定,每个实体类型都将设置为映射到与公开实体的 DbSet 属性名称相同的数据库表。 如果给定实体不存在 DbSet,则使用类名称。
[Table("blogs", Schema = "blogging")]
[Comment("Blogs managed on the website")]//表注释
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.ToTable("blogs");
// modelBuilder.Entity()
// .ToTable("blogs", schema: "blogging");
modelBuilder.Entity<Blog>()
.HasComment("Blogs managed on the website");
}
# 模型的数据注释和FluentAPI的属性定义
.HasKey(c => c.LicensePlate);[Key]//主键
.HasName("PrimaryKey_BlogId");//主键名
.Ignore(b => b.LoadedFromDatabase);[NotMapped]//排除类型
HasColumnName("blog_id");[Column("blog_id")]//列名
HasColumnType("varchar(200)");[Column(TypeName = "varchar(200)")]//列数据类型
HasMaxLength(500);[MaxLength(500)]//最大长度
HasPrecision(14, 2);[Precision(14, 2)]//属性配置为精度为 14 和小数位数为 2
IsUnicode(false);[Unicode(false)]//Unicode
IsRequired();[Required]//必须属性
.HasComment();[Comment("Blogs managed on the website")]//列注释
.HasColumnOrder(0);[Column(Order = 0)]//列顺序
.HasDefaultValue(3);//默认值
.HasDefaultValueSql("getdate()");//默认值
public class Blog
{
[Column("blog_id")]
[MaxLength(500)]
public int BlogId { get; set; }
[Column(TypeName = "varchar(200)")]
public string Url { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.BlogId)
.HasColumnName("blog_id");
modelBuilder.Entity<Blog>(
eb =>
{
eb.Property(b => b.Url).HasColumnType("varchar(200)");
eb.Property(b => b.Rating).HasColumnType("decimal(5, 2)");
});
}
# 分组配置
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder
.Property(b => b.Url)
.IsRequired();
}
}
new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());
# 查询数据 关联查询Include
支持的操作包括:Where、OrderBy、OrderByDescending、ThenBy、ThenByDescending、Skip 和 Take。
var blogs = context.Blogs.ToList();//加载所有数据
.Include(blog => blog.Posts).ToList();//Posts所有数据
.Single(b => b.BlogId == 1);//加载单个实体
.SingleOrDefault(b => b.BlogId == 1);//
.Where(b => b.Url.Contains("dotnet")).ToList();//筛选
.OrderByDescending(blog => blog.Rating).Select(
blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog.Url) })
.ToList();排序
.Include(
blog => blog.Posts
.Where(post => post.BlogId == 1)
.OrderByDescending(post => post.Title)
.Take(5))
.ToList();
context.Blogs.Add(blog);//添加数据
context.Blogs.Remove(blog);//删除数据
context.SaveChanges();//保存
第一个EFCore应用
连接mysql(Pomelo.EntityFrameworkCore.MySql)
string connection = “server=127.0.0.1;userid=root;pwd=123456;port=3306;database=blogging;sslmode=none;Convert Zero Datetime=True”;//
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseMySql(connection, new MySqlServerVersion(new System.Version(5, 7, 37)));
1.创建一个控制台程序
2.添加包
Microsoft.EntityFrameworkCore.Sqlite
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools
3.增加model类Model.cs //是一对多的
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public string DbPath { get; }
public BloggingContext()
{
var folder = Environment.SpecialFolder.LocalApplicationData;
var path = Environment.GetFolderPath(folder);//
DbPath = System.IO.Path.Join(path, "blogging.db");
}
// The following configures EF to create a Sqlite database file in the
// special "local" folder for your platform.
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite($"Data Source={DbPath}");
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; } = new();
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
4.在程序包管理器控制台
Add-Migration FirstMigration
Update-Database
5.Program.cs(进行CRUD)
using (var db = new BloggingContext())
{
// Note: dababase path
Console.WriteLine($"Database path: {db.DbPath}.");
//Create
//Console.WriteLine("Inserting a new blog");
//db.Add(new Blog { Url = "http://baidu.com" });//http://blogs.msdn.com/adonet;
//db.SaveChanges();
// Read
Console.WriteLine("Querying for a blog");
var blog = db.Blogs
.OrderBy(b => b.BlogId)
.FirstOrDefault();
//var blogs = db.Blogs.Where(b => b.BlogId > 1);
//foreach (var item in blogs)
//{
// Console.WriteLine($"{item.Url}");
//}
// Update
Console.WriteLine("Updating the blog and adding a post");
blog!.Url = "https://devblogs.microsoft.com/dotnet";
blog.Posts.Add(
new Post { Title = "Hello World", Content = "I wrote an app using EF Core!" });
db.SaveChanges();
Delete
Console.WriteLine("Delete the blog");
db.Remove(blog);
db.SaveChanges();
}
命令行
//需要添加所需的包
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Design//添加 EF Core 工具所需的包。
dotnet tool install --global dotnet-ef//将安装 dotnet ef,用于创建迁移和基架的工具。
dotnet ef migrations add InitialCreate --context PizzaContext//创建数据库的迁移
dotnet ef database update --context PizzaContext//将应用迁移生成数据库。
using Microsoft.EntityFrameworkCore;
using ContosoPizza.Models;
namespace ContosoPizza.Data;
public class PizzaContext : DbContext
{
public PizzaContext (DbContextOptions<PizzaContext> options)
: base(options)
{
}
public DbSet<Pizza> Pizzas => Set<Pizza>();//表名
public DbSet<Topping> Toppings => Set<Topping>();
public DbSet<Sauce> Sauces => Set<Sauce>();
}
//-------------------
builder.Services.AddSqlite<PizzaContext>("Data Source=ContosoPizza.db");
两种配置方式
1、Data Annotation
把配置以特性(Annotation)的形式标注在实体类中。
[Table(“T_Books”)]
public class Book
{
}
优点:简单;缺点:耦合。
2、Fluent API
builder.ToTable(“T_Books”);
把配置写到单独的配置类中。
缺点:复杂;优点:解耦
Guid主键
1、 Guid算法(或UUID算法)生成一个全局唯一的Id。适合于分布式系统,在进行多数据库数据合并的时候很简单。优点:简单,高并发,全局唯一;缺点:磁盘空间占用大。
yzk开源的高效批量修改、删除的开源项目Zack.EFCore.Batch
1、经典步骤:建实体类;建DbContext;生成数据库;编写调用EF Core的业务代码。
程序包管理器控制台
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Pomelo.EntityFrameworkCore.MySql
optionsBuilder.UseMySql("server=localhost;user=root;password=root;database=ef",
new MySqlServerVersion(new Version(5, 6, 0)));
Install-Package Npgsql.EntityFrameworkCore.PostgreSQL
optionsBuilder.UseNpgsql("Host=127.0.0.1;Database=ef;Username=postgres;Password=123456");
//Book.cs
public class Book
{
public long Id { get; set; }//主键
[Required]
[MaxLength(100)]
public string Title { get; set; }//标题
public DateTime PubTime { get; set; }//发布日期
public double Price { get; set; }//单价
}
//创建实现了IEntityTypeConfiguration接口的实体配置类,配置实体类和数据库表的对应关系
class BookEntityConfig : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books");
//builder.Property(e => e.Title).HasMaxLength(50).IsRequired();
//builder.Property(e => e.AuthorName).HasMaxLength(20).IsRequired();
}
}
//创建继承自DbContext的类
class TestDbContext:DbContext
{
public DbSet<Book> Books { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connStr = "Server=.;Database=demo1;Trusted_Connection=True;MultipleActiveResultSets=true";
optionsBuilder.UseSqlServer(connStr);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
//插入数据
//只要操作Books属性,就可以向数据库中增加数据,但是通过C#代码修改Books中的数据只是修改了内存中的数据。对Books做修改后,需要调用DbContext的异步方法SaveChangesAsync()把修改保存到数据库。也有同步的保存方法SaveChanges(),但是用EF Core都推荐用异步方法。
//查询数据
1、DbSet实现了IEnumerable<T>接口,因此可以对DbSet实施Linq操作来进行数据查询。EF Core会把Linq操作转换为SQL语句。面向对象,而不是面向数据库(SQL)。
2、ctx.Books.Where(b => b.Price > 80)
Book b1 = ctx.Books.Single(b => b.Title== "零基础趣学C语言");
Book b2 = ctx.Books.FirstOrDefault(b=>b.Id==9);
3、可以使用OrderBy操作进行数据的排序
IEnumerable<Book> books = ctx.Books.OrderByDescending(b => b.Price);
//查询数据2
1、GroupBy也可以
var groups = ctx.Books.GroupBy(b => b.AuthorName)
.Select(g => new { AuthorName = g.Key, BooksCount = g.Count(), MaxPrice = g.Max(b => b.Price) });
foreach(var g in groups)
{
Console.WriteLine($"作者名:{g.AuthorName},著作数量:{g.BooksCount},最贵的价格:{g.MaxPrice}");
}
2、大部分Linq操作都能作用于EF Core。
//修改、删除
1、要对数据进行修改,首先需要把要修改的数据查询出来,然后再对查询出来的对象进行修改,然后再执行SaveChangesAsync()保存修改。
var b = ctx.Books.Single(b=>b.Title== "数学之美");
b.AuthorName = "Jun Wu";
await ctx.SaveChangesAsync();
2、删除也是先把要修改的数据查询出来,然后再调用DbSet或者DbContext的Remove方法把对象删除,然后再执行SaveChangesAsync()保存修改。
var b = ctx.Books.Single(b => b.Title == "数学之美");
ctx.Remove(b);//也可以写成ctx.Books.Remove(b);
await ctx.SaveChangesAsync();
//批量修改、删除 性能低:查出来,再一条条Update、Delete,
ASP.NET Core MVC 登录验证
1,创建一个mvc的项目
2,添加包,创建一个实体类,相应的上下文类。
3,数据库的迁移,实现,program.cs的配置。
4,在HomeController添加[Authorize],
5, 添加一个User控制器,以及视图Login,添加内容_Layout.cshtml
Microsoft.EntityFrameworkCore.Sqlite
Pomelo.EntityFrameworkCore.MySql
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools
Add-Migration InitialCreate//实现迁移
Update-database//生成数据库
//User.cs
public class User
{
public int Id { get; set; }
public string Account { get; set; }
public string Password { get; set; }
}
//MyDbContext.cs
using Microsoft.EntityFrameworkCore;
public class MyDbContext:DbContext
{
public DbSet<User> Users { get; set; }
public MyDbContext(DbContextOptions options) : base(options)
{
}
}
//program.cs
//builder.Services.AddSqlite("Data Source=ContosoPizza.db");//连接Sqlite
builder.Services.AddDbContext<MyDbContext>(options=>options.UseMySql("server=localhost;user=root;password=123456;database=Myhaha",
new MySqlServerVersion(new Version(5, 6, 0))));
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)//身份验证
.AddCookie(options =>
{
options.LoginPath = "/User/Login";//初识路径
});
app.UseAuthentication();
//UserController.cs
public class UserController : Controller
{
private readonly MyDbContext _context;
public UserController(MyDbContext myDbContext)
{
_context = myDbContext;
}
public IActionResult Index()
{
return View();
}
public IActionResult Login(string returnUrl)
{
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[HttpPost]
public async Task< IActionResult> Login(UserLoginRequest request)
{
if(await _context.Users.AnyAsync(a => a.Account == request.Account && a.Password == request.Password))
//if (request.Account=="admin"&&request.Password=="admin")
{
var claim = new List<Claim>()
{
new Claim(ClaimTypes.Name,request.Account),//保存了数据。
};
var clainmnsIdentity=new ClaimsIdentity(claim, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(clainmnsIdentity),
new AuthenticationProperties
{
IsPersistent = true,//持久cookie
});
}
else{ return RedirectToAction(nameof(Login));}
return Redirect(request.ReturnUrl ?? "/");
//return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync();
return RedirectToAction(nameof(Login));
}
}
public class UserLoginRequest : User
{
public string ReturnUrl { get; set; }
}
//Login.cshtml
<form asp-action="Login" method="post">
<input type="hidden" name="returnUrl" value="@ViewBag.ReturnUrl" />
<input type="text" name="account" value="" />
<input type="password" name="password" value="" />
<input type="submit" value="登录" />
</form>
//_Layout.cshtml
添加内容
<li class="nav-item">
@User.Identity.Name
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="User" asp-action="Logout">退出登录</a>
</li>
数据库表之间的关系:一对一、一对多、多对多
一对多:HasOne(…).WithMany(…);
一对一:HasOne(…).WithOne (…);
多对多:HasMany (…).WithMany(…);
1、IQueryable books = ctx.Books;
books.Where(b => b.Price > 1.1)
2、IEnumerable books = ctx.Books;
books.Where(b => b.Price > 1.1)
//1、文章实体类Article、评论实体类Comment。一篇文章对应多条评论。
public class Article
{
public long Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List<Comment> Comments { get; set; }
= new List<Comment>();
}
public class Comment
{
public long Id { get; set; }
public Article Article { get; set; }
public string Message { get; set; }
}
//一对多:关系配置
class ArticleConfig : IEntityTypeConfiguration<Article>
{
public void Configure(EntityTypeBuilder<Article> builder)
{
builder.ToTable("T_Articles");
builder.Property(a => a.Content).IsRequired().IsUnicode();
builder.Property(a => a.Title).IsRequired().IsUnicode().HasMaxLength(255);
}
}
class CommentConfig : IEntityTypeConfiguration<Comment>
{
public void Configure(EntityTypeBuilder<Comment> builder)
{
builder.ToTable("T_Comments");
builder.HasOne<Article>(c=>c.Article).WithMany(a => a.Comments).IsRequired();//HasForeignKey(c=>c.ArticleId)
builder.Property(c=>c.Message).IsRequired().IsUnicode();
}
}
//获取关系数据
Article a = ctx.Articles.Include(a=>a.Comments).Single(a=>a.Id==1);
Console.WriteLine(a.Title);
ctx.Articles.Where(a=>a.Comments.Any(c=>c.Message.Contains("微软")));
ctx.Comments.Where(c => c.Message.Contains("微软"))
.Select(c => c.Article).Distinct();
foreach(Comment c in a.Comments)
{
Console.WriteLine(c.Id+":"+c.Message);
}
//Include定义在Microsoft.EntityFrameworkCore命名空间中
//关联查询
//CommentConfig:
builder.HasOne<Article>(c=>c.Article).WithMany(a => a.Comments).IsRequired();
//ArticleConfig:
builder.HasMany<Comment>(a => a.Comments).WithOne(c => c.Article).IsRequired();
class Order
{
public long Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public Delivery Delivery { get; set;}
}
class Delivery
{
public long Id { get; set; }
public string CompanyName { get; set; }
public String Number { get; set; }
public Order Order { get; set; }
public long OrderId { get; set; }
}
1、builder.HasOne<Delivery>(o => o.Delivery).WithOne(d => d.Order).HasForeignKey<Delivery>(d=>d.OrderId);
2、测试插入和获取数据。
class Student
{
public long Id { get; set; }
public string Name { get; set; }
public List<Teacher> Teachers { get; set; } = new List<Teacher>();
}
class Teacher
{
public long Id { get; set; }
public string Name { get; set; }
public List<Student> Students { get; set; } = new List<Student>();
}
builder.HasMany<Teacher>(s => s.Teachers).WithMany(t=>t.Students).UsingEntity(j=>j.ToTable("T_Students_Teachers"));
1、IQueryable只是代表一个“可以放到数据库服务器去执行的查询”,它没有立即执行,只是“可以被执行”而已。
2、对于IQueryable接口调用非终结方法的时候不会执行查询,而调用终结方法的时候则会立即执行查询。
3、终结方法:遍历、ToArray()、ToList()、Min()、Max()、Count()等;
4、非终结方法:GroupBy()、OrderBy()、Include()、Skip()、Take()等。
5、简单判断:一个方法的返回值类型如果是IQueryable类型,那么这个方法一般就是非终结方法,否则就是终结方法。
1、IQueryable是一个待查询的逻辑,因此它是可以被重复使用的。
2、IQueryable books = ctx.Books.Where(b => b.Price <= 8);
Console.WriteLine(books.Count());
Console.WriteLine(books.Max(b=>b.Price));
var books2 = books.Where(b=>b.PubTime.Year>2000);
1、DataReader:分批从数据库服务器读取数据。内存占用小、 DB连接占用时间长;
2、DataTable:把所有数据都一次性从数据库服务器都加载到客户端内存中。内存占用大,节省DB连接。
验证IQueryable用什么方式
1、用insert into select多插入一些数据,然后加上Delay/Sleep的遍历IQueryable。在遍历执行的过程中,停止SQLServer服务器。
IQueryable内部就是在调用DataReader。
2、优点:节省客户端内存。
缺点:如果处理的慢,会长时间占用连接。
//如何一次性加载数据到内存
1、一次性加载数据到内存:用IQueryable的ToArray()、ToArrayAsync()、ToList()、ToListAsync()等方法。
2、等ToArray()执行完毕,再断服务器试一下。
//何时需要一次性加载
1、场景1:遍历IQueryable并且进行数据处理的过程很耗时。
2、场景2:如果方法需要返回查询结果,并且在方法里销毁DbContext的话,是不能返回IQueryable的。必须一次性加载返回。
3、场景3:多个IQueryable的遍历嵌套。很多数据库的ADO.NET Core Provider是不支持多个DataReader同时执行的。把连接字符串中的MultipleActiveResultSets=true删掉,其他数据库不支持这个。
//对应异步方法
1、SaveChanges()、SaveChangesAsync()
2、异步方法大部分是定义在Microsoft.EntityFrameworkCore这个命名空间下EntityFrameworkQueryableExtensions等类中的扩展方法,记得using。
3、AddAsync()、AddRangeAsync()、AllAsync()、AnyAsync、AverageAsync、ContainsAsync、CountAsync、FirstAsync、FirstOrDefaultAsync、ForEachAsync、LongCountAsync、MaxAsync、MinAsync、SingleAsync、SingleOrDefaultAsync、SumAsync等
https://dapper-tutorial.net/step-by-step-tutorial
https://www.w3cschool.cn/dapperorm/
https://www.jb51.net/article/216497.htm
https://www.codenong.com/cs106392582/
https://www.cnblogs.com/yixuanhan/p/9238781.html
https://blog.csdn.net/dxm809/article/details/112038117
using Dapper;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.SqlClient;
List<User> user = new List<User>();
string strcon = "Database=traytest;Data Source=localhost;User Id=root;Password=123456;CharSet=utf8;port=3306";
IDbConnection db = new MySqlConnection(strcon);
db.Open();
//queryid(28);
Insert(new User { name= "2222",age="2222" });
//查询
void query()
{
user = db.Query<User>("Select * From user").ToList();
foreach (var item in user)
{
Console.WriteLine("name=" + item.name + "~~~age=" + item.age);
}
}
void queryid(int id)
{
user = db.Query<User>($"Select * From user where id={id}").ToList();
foreach (var item in user)
{
Console.WriteLine("name=" + item.name + "~~~age=" + item.age);
}
}
//添加
void Insert(User user)
{
string insertSqlStr = $"INSERT INTO user(id,Name,age)VALUES(null,{user.name},{user.age})";
//db.Execute(insertSqlStr, user); //这种是按实体插入
db.Execute(insertSqlStr); //这种是按实体插入
}
public class User
{
public int id { get; set; }
public string name { get; set; }
public string age { get; set; }
}
-------------------
//查询
#region Query
void queryid(int id)
{
user = db.Query<User>($"Select * From user where id={id}").ToList();
foreach (var item in user)
{
Console.WriteLine("name=" + item.name + "~~~age=" + item.age);
}
}
#endregion
#region Update
//更新
void Update(User user)
{
string sql = "UPDATE user SET name = @name,age=@age WHERE id = (@id)";
db.Execute(sql, user); //这种是按实体插入
Console.WriteLine("更新成功");
}
//更新多个
void UpdateNumbs(List<User> users)
{
string sql = "UPDATE user SET name = @name,age=@age WHERE id = (@id)";
db.Execute(sql, users); //这种是按实体插入
Console.WriteLine("更新成功多个");
}
#endregion
#region Delete
//删除
void Delete(User user)
{
string sql = "DELETE FROM user WHERE id = @id";
db.Execute(sql, user); //这种是按实体删除
Console.WriteLine("删除成功");
}
//删除多个
void DeleteNumbs(List<User> users)
{
string sql = "DELETE FROM user WHERE id = @id";
db.Execute(sql, users); //这种是按实体删除多个
Console.WriteLine("删除多个");
}
#endregion
#region Add
//添加
void Insert(User user)
{
//string insertSqlStr = $"INSERT INTO user(id,name,age)VALUES(null,{user.name},{user.age})";
string insertSqlStr = $"INSERT INTO user(id,name,age)VALUES(null,(@name),(@age))";
//db.Execute(insertSqlStr, user); //这种是按实体插入
db.Execute(insertSqlStr, user); //这种是按实体插入
Console.WriteLine("添加成功");
}
//添加多个
void InsertNumbs(List<User> users)
{
string insertSqlStr = $"INSERT INTO user(id,name,age)VALUES(null,(@name),(@age))";
//db.Execute(insertSqlStr, user); //这种是按实体插入
db.Execute(insertSqlStr, users); //这种是按实体插入
Console.WriteLine("添加多个成功");
}
#endregion
官网
//查询所有
using SqlSugar;
using MySql.Data;
Demo();
static void Demo()
{
//创建数据库对象
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = "Database=traytest;Data Source=localhost;User Id=root;Password=123456;CharSet=utf8;port=3306",
//ConnectionString = "server=localhost;Database=traytest;Uid=root;Pwd=123456; AllowLoadLocalInfile=true",
DbType = DbType.MySql,
//DbType = DbType.MySqlConnector,
IsAutoCloseConnection = true
});
//调试SQL事件,可以删掉(要放在执行方法之前)
db.Aop.OnLogExecuting = (sql, pars) =>
{
Console.WriteLine(sql);//输出sql,查看执行sql
//5.0.8.2 获取无参数化 SQL
//UtilMethods.GetSqlString(DbType.SqlServer,sql,pars)
};
//查询表的所有
//var list = db.Queryable().ToList();
//foreach (var item in list)
//{
// Console.WriteLine("name=" + item.Name + "~~~age=" + item.Age);
//}
//插入
//db.Insertable(new User() { Age="jack", Name = "jack" }).ExecuteCommand();
//更新
//db.Updateable(new User() { Id = 30, Age = "jack2", Name = "jack2" }).ExecuteCommand();
//删除
//db.Deleteable().Where(it => it.Id == 30).ExecuteCommand();
}
//实体与数据库结构一样
public class User
{
//数据是自增需要加上IsIdentity
//数据库是主键需要加上IsPrimaryKey
//注意:要完全和数据库一致2个属性
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
public string Age { get; set; }
public string Name { get; set; }
}
官网
IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.MySql, "Database=traytest;Data Source=localhost;User Id=root;Password=123456;CharSet=utf8;port=3306")
.UseAutoSyncStructure(true) //自动同步实体结构到数据库,FreeSql不会扫描程序集,只有CRUD时才会生成表。
.Build(); //请务必定义成 Singleton 单例模式
List<User> select = fsql.Select<User>().ToList();
foreach (var item in select)
{
Console.WriteLine(item.Age);
}
//实体与数据库结构一样
public class User
{
public int Id { get; set; }
public string Age { get; set; }
public string Name { get; set; }
}
参考链接:
官方文档
易百教程
asp.net连接mysql数据库+mysql公共类
https://blog.csdn.net/qq_23018459/article/details/79446935
对理解有帮助
c#中用来批量更新数据库SqlCommandBuilder