为什么EF返回的是代理类而不是实际实体
本文关键字:实体 代理 EF 返回 为什么 | 更新日期: 2023-09-27 18:26:23
当我想要实际的实体类时,实体框架返回Proxies时遇到了问题。第一次运行代码时,一切都正常运行(没有代理),但之后的每次迭代,我的一个DbSet总是返回代理,而不是实际类型。
我在每次迭代后都会处理上下文,所以我不明白为什么第一次迭代有效,而之后的每次都无效。
我的代码在这一行失败了。我的所有POCO都设置了Table属性,但因为它返回了一个代理类,所以没有表属性。
TableAttribute attrib = (TableAttribute)attributes.Single();
在我销毁对象后,DbContext中是否存在一些幕后静态魔法?
我使用以下将我的对象移动到内存中
MajorClasses = ctx.MajorClasses.ToArray();
我也试过
MajorClasses = ctx.MajorClasses.AsNoTracking().ToArray();
在我的OnModelCreating中,我有以下设置
base.Configuration.ProxyCreationEnabled = false;
base.Configuration.LazyLoadingEnabled = false;
您可以将ObjectContext.ContextOptions.ProxyCreationEnabled
设置为false。这将阻止您使用EF的一些奇特功能,如延迟加载和我相信的更改跟踪。
就你的应用程序而言,它应该能够像对待代理所代表的类型一样对待代理。你有什么特别的问题吗?
编辑
我们有一些代码需要POCO类型而不是代理类型,我们执行以下操作来检测当前类型是否为代理。
if (entityType.BaseType != null && entityType.Namespace == "System.Data.Entity.DynamicProxies")
{
entityType = entityType.BaseType;
}
要关闭实体框架5中的代理创建,您可以使用以下
_dbContext.Configuration.ProxyCreationEnabled = false;
在使用上下文提取数据之前,只需设置一次此属性。
默认情况下,EF使用更改跟踪并使用所有实体的内存缓存。使用EF时,可以使用不同的"合并选项"。默认情况下,EF 4.1设置为AppendOnly Merge Option。据我所知,这意味着如果您已经查询了一个实体,那么后续查询将从缓存中获取该实体(如果数据库中没有检测到更改)。因此,您可能会看到缓存的实体正在返回。
在EF 4.1中,您可以使用NoTracking Merge Option。这将转到每个调用的数据库中。
在EF 6.1.3中,您可以使用获得正确的类型
using (var context = new BloggingContext()) {
var blog = context.Blogs.Find(1);
var entityType = ObjectContext.GetObjectType(blog.GetType());
}
请注意,如果传递给GetObjectType的类型是不是代理类型的实体类型的实例,则仍会返回实体类型。这意味着您可以始终使用此方法来获取实际的实体类型,而无需进行任何其他检查来查看该类型是否为代理类型。
来自MSDN
简单的解决方案是,您缺少一些必须包含的对象,并且在获取值之前也要执行此操作
_dbContext.Configuration.ProxyCreationEnabled = false;
在我的案例中,通过将Lazy Loading Enabled
设置为false
解决了此问题。
- 打开.edmx(图表)
- 按F4调出属性
- 将
Lazy Loading Enabled
设置为false
- 保存并重新生成