1. 基本查询
1.1 加载全部数据
using System.Linq;
using (var context = new LibingContext())
{
var roles = context.Roles.ToList();
}
1.2 加载单个实体
using (var context = new LibingContext())
{
var role = context.Roles.FirstOrDefault(t => t.RoleID == );
}
using (var context = new LibingContext())
{
var role = context.Roles.Find();
}
注:Find()根据主键值查询返回单个实体。
1.3 筛选条件
using (var context = new LibingContext())
{
var roles = context.Roles
.Where(t => t.RoleName == "管理员")
.ToList();
}
2. 加载关联数据
Entity Framework Core可以在实体模型中使用导航属性,来加载关联数据。
常见的3中关联数据加载方式:
(1)预先加载(Eager Loading):关联数据作为初始查询的一部分从数据库中加载
(2)显式加载(Explicit Loading):关联数据在后续用到时显式指定从数据中加载
(3)延迟加载(Lazy Loading):关联数据通过导航属性,以透明方式从数据库中加载
2.1 预先加载
使用Include()指定需要包含在查询结果中的关联数据。
using System.Linq;
using Microsoft.EntityFrameworkCore;
using (var context = new LibingContext())
{
var categories = context.Categories
.Include(t => t.Products)
.ToList();
}
2.2 显式加载
显式加载通过一个导航属性DbContext.Entry(...)API。
using (var context = new LibingContext())
{
var category = context.Categories.Find(); context.Entry(category)
.Collection(t => t.Products)
.Load(); category.Products.ForEach(product =>
{
Console.WriteLine("ProductID:{0},ProductName:{1}", product.ProductID, product.ProductName);
});
}
显式加载通过相关的实体的聚合运算符,而无需加载到内存的操作。
using (var context = new LibingContext())
{
var category = context.Categories.Find(); int count = context.Entry(category)
.Collection(t => t.Products)
.Query()
.Count();
}
筛选加载到内存的关联实体数据。
using (var context = new LibingContext())
{
var category = context.Categories.Find(); var products = context.Entry(category)
.Collection(t => t.Products)
.Query()
.Where(t => t.UnitPrice >= )
.ToList();
}
3. 跟踪与非跟踪
3.1 跟踪查询
Entity Framework Core跟踪状态的实体,在检测到改动的情况下,调用SaveChanges()时,将持久保存数据库中。
using (var context = new LibingContext())
{
var product = context.Products.Find();
product.UnitPrice = 100m; context.SaveChanges();
}
3.2 非跟踪查询
非跟踪查询在对查询数据只读情况下,可以加快执行。
using (var context = new LibingContext())
{
var products = context.Products
.AsNoTracking()
.ToList();
}
更改默认跟踪上下文实例级别的行为:
using (var context = new LibingContext())
{
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var products = context.Products
.ToList();
}
3.3 跟踪与投影
即使查询的结果类型不是实体类型,如果结果包含实体类型它们将仍在默认情况下跟踪。
在下面的查询,它返回匿名类型的实例Category
集将跟踪结果中。
using (var context = new LibingContext())
{
var categories = context.Categories
.Select(t => new
{
Category = t,
Products = t.Products.Count()
});
}
如果结果集不包含任何实体类型,会不执行任何跟踪。
在下面的查询,这将返回一个匿名类型使用某些实体(但不实际实体类型的实例)中的值时,没有任何跟踪执行。
using (var context = new LibingContext())
{
var products = context.Products
.Select(t => new
{
ProductID = t.ProductID,
PrudctName = t.ProductName
});
}
4. 原始SQL查询
EntityFramework Core使用原始SQL查询限制条件:
(1)SQL查询返回字段必须属于实体类型
(2)SQL查询必须返回实体类型的所有属性
4.1 基本原始SQL查询
使用FromSql扩展方法,基于原始的 SQL 查询的 LINQ 查询。
using (var context = new LibingContext())
{
var products = context.Products
.FromSql("SELECT * FROM [dbo].[Product]")
.ToList();
}
使用原始的 SQL 查询来执行存储的过程。
CREATE PROCEDURE USP_GetProducts
AS
BEGIN
SELECT * FROM [dbo].[Product]
END
using (var context = new LibingContext())
{
var products = context.Products
.FromSql("EXECUTE [dbo].[USP_GetProducts]")
.ToList();
}
4.2 传递参数
SQL参数化可以防止收到SQL注入攻击。
CREATE PROCEDURE USP_GetProductsByUnitPrice
@UnitPrice DECIMAL(18, 2)
AS
BEGIN
SELECT * FROM [dbo].[Product]
WHERE [UnitPrice] >= @UnitPrice
END
using (var context = new LibingContext())
{
decimal unitprice = 100m;
var products = context.Products
.FromSql("EXECUTE [dbo].[USP_GetProducts] {0}", unitprice)
.ToList();
}
using System.Data;
using System.Data.SqlClient;
using (var context = new LibingContext())
{
var unitprice = new SqlParameter("@UnitPrice", SqlDbType.Decimal);
unitprice.Value = 100m; var products = context.Products
.FromSql("EXECUTE [dbo].[USP_GetProducts] @UnitPrice", unitprice)
.ToList();
}
5. 异步查询
异步操作使用场景:当等待一个比较耗时的操作时,使用异步来释放当前的托管线程而无需等待,不会阻塞当前线程的运行。
异步操作在主应用程序线程以外的线程中执行,应用程序可在异步方法执行其任务时继续执行。
异步查询在数据库中执行查询时可以避免阻止线程。
Entity Framework Core提供的异步查询扩展方法包括:ToListAsync(),ToArrayAsync(),SingleAsync()等。
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
public async Task<List<Product>> GetProductsAsync()
{
using (var context = new LibingContext())
{
return await context.Products.ToListAsync();
}
}