EF高级用法
一、DBContext生命周期
1.数据库连接
DBContext对象是一个上下文,可以理解成一个数据库连接实例;包含了一系列的数据操作。
2.实现了IDisposable接口
DBContext对象很耗系统资源;一般使用Using包裹(使用完马上自动释放)。
3.SaveChanges方法
SaveChanges是以DBContext为维度的,会自动开启事务去执行多个数据库操作。
4.建议用法
一次请求一个DBContext实例,用完尽快释放;不要单例,也不要多线程使用同一个DBContext。
二、延迟加载(懒加载)/贪婪加载
1.原理解析
只有在使用到的时候才去执行获取数据(生成对应的Sql,按需获取,思想是延迟一切可以延迟的。
而贪婪加载是把对象的关联数据也查询出来,关联数据是(Include)导航属性的数据。
代码如下(示例):
public static void TestLoading()
{
using (CodeFirstContext ctx = new CodeFirstContext())
{
Console.WriteLine($"LazyLoadingEnabled:{ctx.Configuration.LazyLoadingEnabled}");
//ctx.Configuration.LazyLoadingEnabled = true;
var list = ctx.Clients.Where(c => c.Id > 1);
foreach (var item in list)
{
Console.WriteLine(item.ClientName);
}
// Sql:
// SELECT
// [Extent1].[Id] AS[Id],
//[Extent1].[Name] AS[Name],
//[Extent1].[Tel] AS[Tel],
//[Extent1].[Sex] AS[Sex],
//[Extent1].[Address] AS[Address],
//[Extent1].[CreateTime] AS[CreateTime],
//[Extent1].[CreatorId] AS[CreatorId]
//FROM[dbo].[Client] AS[Extent1]
//WHERE[Extent1].[Id] > 1
var clientList = ctx.Clients.Include("OrderInfos").Where(c => c.Id > 1);
// Sql:
// SELECT
//[Project1].[Id] AS[Id],
//[Project1].[Name] AS[Name],
//[Project1].[Tel] AS[Tel],
//[Project1].[Sex] AS[Sex],
//[Project1].[Address] AS[Address],
//[Project1].[CreateTime] AS[CreateTime],
//[Project1].[CreatorId] AS[CreatorId],
//[Project1].[C1] AS[C1],
//[Project1].[Id1] AS[Id1],
//[Project1].[ClientId] AS[ClientId],
//[Project1].[ProductId] AS[ProductId],
//[Project1].[Amount] AS[Amount],
//[Project1].[Price] AS[Price],
//[Project1].[CreateTime1] AS[CreateTime1],
//[Project1].[CreatorId1] AS[CreatorId1]
//FROM(SELECT
// [Extent1].[Id] AS[Id],
// [Extent1].[Name] AS[Name],
// [Extent1].[Tel] AS[Tel],
// [Extent1].[Sex] AS[Sex],
// [Extent1].[Address] AS[Address],
// [Extent1].[CreateTime] AS[CreateTime],
// [Extent1].[CreatorId] AS[CreatorId],
// [Extent2].[Id] AS[Id1],
// [Extent2].[ClientId] AS[ClientId],
// [Extent2].[ProductId] AS[ProductId],
// [Extent2].[Amount] AS[Amount],
// [Extent2].[Price] AS[Price],
// [Extent2].[CreateTime] AS[CreateTime1],
// [Extent2].[CreatorId] AS[CreatorId1],
// CASE WHEN([Extent2].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS[C1]
// FROM[dbo].[Client] AS[Extent1]
// LEFT OUTER JOIN[dbo].[Order] AS[Extent2] ON[Extent1].[Id] = [Extent2].[ClientId]
// WHERE[Extent1].[Id] > 1
//) AS[Project1]
//ORDER BY[Project1].[Id] ASC, [Project1].[C1] ASC
foreach (var item in clientList)
{
Console.WriteLine(item.ClientName);
}
}
}
2.延迟查询在Linq中的使用
IEnumerable(Linq to object):处理的是内存数据,原理是使用委托&迭代器来完成的延迟查询。
IQueryable(Linq to Sql):处理的数据库中的数据,原理是使用Expression(生成Sql语句)、ElementType(指定一个查询需要返回的结果类型)和IQueryProvider(获取与此数据源相关联的查询提供程序。)来完成的延迟查询。
代码如下(示例):
public static void TestLazyQueryFromLinq()
{
//Linq to object(操作内存数据)
int[] randomSleepTimes = new int[] {
1, 2, 4, 5, 6, 7, 8 };
//IEnumerable+委托+迭代器完成的延迟查询---处理的是内存数据
IEnumerable<int> list = randomSleepTimes.Where(rv =>
{
System.Threading.Thread.Sleep(rv * 1000);
return rv > 0;
});
foreach (var item in list)
{
Console.WriteLine($"{DateTime.Now} {item}");
}
//Linq to Sql
using (CodeFirstContext ctx =

本文详细介绍了Entity Framework(EF)中DBContext的生命周期,包括数据库连接、IDisposable接口的实现以及SaveChanges方法的事务处理。此外,还探讨了延迟加载(懒加载)和贪婪加载的原理及使用,强调了在Linq查询中的应用。对于导航属性,文章讲解了主外键关系、Include方法以及自增Id的自动填充。最后,文章深入讨论了事务管理,包括SaveChanges自动开启的事务、BeginTransaction、TransactionScope以及分布式事务的实现,并提供了源码下载链接。
最低0.47元/天 解锁文章
978

被折叠的 条评论
为什么被折叠?



