App*_*ose 2 c# linq wpf caching entity-framework
我正在开发一个使用Entity Framework的应用程序,但是我遇到了一些性能问题.想象一下具有一些组合框和数据网格的用户界面(C#,WPF).每次在组合框中选择一个值时,它都会更改数据在网格中显示的条件.看起来实体框架在缓存方面没有我想象的那么灵活.由于条件已更改,底层sql将始终不同(=无EF缓存),每个单元更新将导致对数据库的请求.
有没有什么方法可以在本地缓存表(使用工作导航属性)并仍然使用linq进行选择等而不生成对数据库的任何请求?
也许实体框架从一开始就是一个糟糕的选择,但是使用那些生成的类和linq而不是手动编写很多类和sql真的很方便.(我仍然需要实现一些缓存.)
有什么方法可以在本地缓存表吗?
这是DbContext默认操作,您可以轻松使用该功能.以下是要遵循的基本模式:
context.Products.Where(p => <some intial condion>).Load();
var dataSource = context.Product.Local.Where(p => <some flexible condition>);
Run Code Online (Sandbox Code Playgroud)
请注意,在第2行Local中使用了集合.这是一个DbSet从上下文缓存中返回实体的属性.
具有工作导航属性
由Load()语句加载的任何相关实体将通过关系修正自动相互连接.因此,如果a Product有一个集合Components,你可以这样做:
context.Components.Where(c => <some intial condion>).Load();
Run Code Online (Sandbox Code Playgroud)
如果这会加载上面加载的产品的所有组件,您将看到他们的Components集合现在已填充.
结合这两个步骤的替代方案是:
context.Products.Where(p => <some intial condion>)
.Include(p => p.Components)
.Load();
Run Code Online (Sandbox Code Playgroud)
如果有许多相关表,则必须在各个Load语句和Load语句之间找到平衡Include,因为Includes在一个语句中有许多可能会达到性能.
并仍然使用linq进行选择
如上图所示:灵活的条件.
不产生任何数据库请求
如果您始终Local只处理集合,则这些语句将永远不会查询数据库.但是,寻址导航属性仍可能导致延迟加载.如果你这样做......
context.Products.Where().Load();
context.Components.Where().Load();
Run Code Online (Sandbox Code Playgroud)
...这会填充product.Components集合,但不会将它们标记为已加载,而是context.Products.Include(p => p.Components).因此,在第一种情况下,寻址product.Components将触发延迟加载.类似地,解决根本未加载实体的导航属性也将触发延迟加载.因此,要确保不会触发任何数据库交互,您应该通过以下方式禁用延迟加载:
context.Configuration.LazyLoadingEnabled = false;
Run Code Online (Sandbox Code Playgroud)
... 要么 ...
context.Configuration.ProxyCreationEnabled = false;
Run Code Online (Sandbox Code Playgroud)
后一个选项强制EF创建不能延迟加载的简单POCO对象.
因此,使用这些技术,您可以将上下文用作连接实体的本地缓存.对于上下文应该是短暂的规则,这是一个例外.
一个警告
关系修正不适用于多对多关联.假设和m:n之间存在关系,那么......ProductManufacturer
context.Products.Where().Load();
context.Manufacturers.Where().Load();
Run Code Online (Sandbox Code Playgroud)
...不会填充product.Manufacturers和manufacturer.Products.应该通过以下方式加载多对多关联Include:
context.Products.Where()
.Include(p => p.Manufacturers)
.Load();
Run Code Online (Sandbox Code Playgroud)