c# - 为什么 IQueryable.Select 每次迭代都使用相同的引用
问题描述
我有一个IQueryable
我想在其上执行一个Select
. 在该选择中,我创建一个对象的新实例并运行一个函数,该函数将对象的值从 IQueryable(b) 复制到新创建的对象(新 DTO),然后返回此实例。
IQueryable.Select:
businessLayer.GetAll().Select( b => new DTO().InitInhertedProperties(b)).ToList();
DTO中的功能:
public DTO InitInhertedProperties(Base baseInstance)
{
return Utilities.InitInhertedProperties(this, baseInstance);
}
复制功能:
public static T InitInhertedProperties<T,K>(T instance, K baseClassInstance) where T : K
{
foreach (PropertyInfo propertyInfo in baseClassInstance.GetType().GetProperties())
{
object value = propertyInfo.GetValue(baseClassInstance, null);
if (null != value) propertyInfo.SetValue(instance, value, null);
}
return instance;
}
第一次InitInhertedProperties
调用该方法instance
是一个空对象,baseClassInstance
它具有它应该具有的值:
如您所见:一切都像在第一次迭代中一样。现在进行第二次迭代。
第二次InitInhertedProperties
调用该方法insatnce
不是一个新实例,而是第一次迭代。这baseClassInstance
正是它应该是的:
这只发生在使用IQueryable.Select
. 使用List.Select
结果看起来就像预期的那样。
这意味着这样做可以解决问题。但这只是一种解决方法,而不是解决方案。
businessLayer.GetAll().ToList().Select( b => new DTO().InitInhertedProperties(b)).ToList();
解决方案
当您与IQueryable
您一起工作时,您必须使用表达式。Entity Framework 将检查您放入的每个表达式Select
和OrderBy
其他方法,并尝试将其转换为 SQL。所以你不能在你的 lambda 中调用任意方法,只有 EF 知道
如果你想做一些没有 SQL 引擎直接支持的事情,你可以调用AsEnumerable
:
businessLayer.GetAll().AsEnumerable().Select( ...
(请注意,这AsEnumerable
比ToList
因为它保持懒惰要好)
另一个可能(或可能不,取决于查询提供程序版本)工作的选项是手动构建表达式:
public static Expression<Func<TEntity, TDto>> InitInhertedProperties<TEntity, TDto>() where TDto : TEntity
{
var entity = Expression.Parameter(typeof(BusinessObject), "b");
var newDto = Expression.New(typeof(Dto).GetConstructors().First());
var body = Expression.MemberInit(newDto,
typeof(TDto).GetProperties()
.Select(p => Expression.Bind(p, Expression.Property(entity, p.Name)))
);
return Expression.Lambda<Func<TEntity, TDto>>(body, entity);
}
用法:
var myExp = InitInhertedProperties<BusinessObject, Dto>();
var result = businessLayer.GetAll().Select(myExp).ToList();
推荐阅读
- windows - 无法让 Windows Docker 容器“以管理员身份运行”
- python - 打印列表中整数的一部分
- python - 如何从列表元素中提取特定字符串
- node.js - 使用 ng serve (Angular 6) 时,HttpClientModule 和 mat-icons 将不起作用
- r - UseMethod 和 .S3method() 之间有哪些区别?
- android - 如何设置 CameraX 以进行视频录制 Android 应用程序?
- node.js - 无法让 Puppeteer 工作和安装
- mvc-mini-profiler - SQL查询时间在哪里看?
- python - 为什么我不能在 Opencv 和 Kivy 中使用不同的相机源?
- c++ - 错误:未在此范围内声明“反向”