【发布时间】:2015-02-06 20:44:43
【问题描述】:
我正在尝试使用带有表达式的查找操作创建一个通用存储库。我现在有以下内容(我正在使用 FastMapper 从我的实体对象投影到外部合同对象):
public override List<T> Find(Expression<Func<T, bool>> predicate)
{
var collection = _database.GetCollection<Y>(_collectionName);
return collection.AsQueryable<Y>().Project().To<T>().Where(predicate).ToList();
}
问题是我得到以下异常:“不支持投影后的谓词。”
我可以执行以下操作,但这会严重影响性能,因为它需要在执行过滤之前从数据库中检索每条记录:
public override List<T> Find(Expression<Func<T, bool>> predicate)
{
var collection = _database.GetCollection<Y>(_collectionName);
return collection.AsQueryable<Y>().Project().To<T>().ToList().AsQueryable().Where(predicate).ToList();
}
我想知道是否有一种方法可以将表达式从 T 转换为 Y 对象,以便我可以执行以下操作(我认为这将是最高效的,因为它会将过滤传递到数据库并只对结果集执行项目):
public override List<T> Find(Expression<Func<T, bool>> predicate)
{
var collection = _database.GetCollection<Y>(_collectionName);
return collection.AsQueryable<Y>().Where(predicate).Project().To<T>().ToList();
}
任何帮助将不胜感激。谢谢。
更新
因此,使用来自这个问题 (Question) 的信息,我能够更接近我正在寻找的内容。我现在可以执行以下操作:
public override List<T> Find(Expression<Func<T, bool>> predicate)
{
var newPredicate = TransformPredicateLambda<T, Y>(predicate);
var collection = _database.GetCollection<Y>(_collectionName);
return collection.AsQueryable<Y>().Where(newPredicate).Project().To<T>().ToList();
}
此时我唯一需要解决的是检索 fastmapper 映射(如果属性为空部分):
protected override Expression VisitMember(MemberExpression node)
{
var dataContractType = node.Member.ReflectedType;
var activeRecordType = _typeConverter(dataContractType);
var property = activeRecordType.GetProperty(node.Member.Name);
if (property == null)
{
}
var converted = Expression.MakeMemberAccess(
base.Visit(node.Expression),
property
);
return converted;
}
基本上,我的一些对象可能看起来像这样:
//object used throughout my code
public class Store
{
public string StoreId {get; set;}
public Account Account {get; set;}
...
}
//object used in access layer only
public class Store
{
public string StoreId {get; set;}
public string AccountId {get; set;}
...
}
在我的初始化脚本中,我定义了一个类型适配器,如下所示:
TypeAdapterConfig<Store, Models.Store>.NewConfig()
.MapFrom(a => a.Id, s => s.StoreId != null ? new ObjectId(s.StoreId) : new ObjectId())
.MapFrom(d => d.AccountId, s => s.Account.AccountId)
.IgnoreNullValues(true);
【问题讨论】:
标签: c# mongodb generics repository