如何在 C# class 的计算字段上过滤 Bson 文档?
How to filter Bson Document on a computed field of a C# class?
我有几个 class 需要存储在 MongoDb 集合中,这些 class 有一个共同的基础 class 和定义共同的共同接口领域。每个 class 都有一个同名但实现不同的计算字段。当我尝试查询该字段时,我收到一条消息,指出该字段不受支持
我 运行 在 .Net Core 2.2 控制台应用程序上使用最新的 MongoDb 驱动程序
接口:
public interface ITask
{
ObjectId Id { get; set; }
TaskStatus Status { get; set; }
DateTime Timestamp { get; set; }
string UserId { get; set; }
string ComputedField{ get; }
}
基础Class:
public abstract class BaseTask : ITask
{
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId Id { get; set; }
[BsonElement("Status")]
public TaskStatus Status { get; set; }
[BsonElement("Timestamp")]
public DateTime Timestamp { get; set; }
[BsonElement("UserId")]
public string UserId { get; set; }
public virtual string ComputedField
{
get { return CalculateMD5Hash(Id.ToString()); }
}
}
实际 class 给我的问题
public class MyTask : BaseTask
{
[BsonElement("Field1")]
public Guid Field1{ get; set; }
[BsonElement("ComputedField")]
public override string ComputedField
{
get { return CalculateMD5Hash($"ABC{Field1.ToString()}"); }
}
}
调用 MongoDb 层的包装器
public class TaskService<T> : ITaskService<T> where T : ITask
{
private readonly IPersistanceLayer<ObjectId, object> _pl;
public async Task<T> GetNextTask(string key)
{
var oee = _pl.Mongo.Filter<T>(x => x.ConcurrencyKey==key
, typeof(T).Name).OrderBy(x=> x.Timestamp).FirstOrDefault();
return oee;
}
}
MongoDb层
public IEnumerable<T> Filter<T>(System.Linq.Expressions.Expression<Func<T, bool>> lambda, string collection)
{
var filter = Builders<T>.Filter.Where(lambda);
return _db.GetCollection<T>(collection).Find(filter).ToList();
}
我得到的错误是
[ERR] {document}.ComputedField is not supported.
在集合中,我看到文档在插入时已保存,但计算字段的值已正确存储,唯一的问题是当我尝试查询该字段时
问题是我查找了错误的集合并投射到错误的 class
public class TaskService<T> : ITaskService<T> where T : ITask
{
private readonly IPersistanceLayer<ObjectId, object> _pl;
public async Task<T> GetNextTask(string key)
{
var nextTask= _pl.Mongo.Filter<T>(x => x.ConcurrencyKey==key
, typeof(T).Name).OrderBy(x=> x.Timestamp).FirstOrDefault();
return nextTask;
}
}
在此方法中,T 的类型为 BaseTask 而不是 MyTask,因此我的计算字段不存在,我已更正该问题,现在可以使用了
我有几个 class 需要存储在 MongoDb 集合中,这些 class 有一个共同的基础 class 和定义共同的共同接口领域。每个 class 都有一个同名但实现不同的计算字段。当我尝试查询该字段时,我收到一条消息,指出该字段不受支持
我 运行 在 .Net Core 2.2 控制台应用程序上使用最新的 MongoDb 驱动程序
接口:
public interface ITask
{
ObjectId Id { get; set; }
TaskStatus Status { get; set; }
DateTime Timestamp { get; set; }
string UserId { get; set; }
string ComputedField{ get; }
}
基础Class:
public abstract class BaseTask : ITask
{
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId Id { get; set; }
[BsonElement("Status")]
public TaskStatus Status { get; set; }
[BsonElement("Timestamp")]
public DateTime Timestamp { get; set; }
[BsonElement("UserId")]
public string UserId { get; set; }
public virtual string ComputedField
{
get { return CalculateMD5Hash(Id.ToString()); }
}
}
实际 class 给我的问题
public class MyTask : BaseTask
{
[BsonElement("Field1")]
public Guid Field1{ get; set; }
[BsonElement("ComputedField")]
public override string ComputedField
{
get { return CalculateMD5Hash($"ABC{Field1.ToString()}"); }
}
}
调用 MongoDb 层的包装器
public class TaskService<T> : ITaskService<T> where T : ITask
{
private readonly IPersistanceLayer<ObjectId, object> _pl;
public async Task<T> GetNextTask(string key)
{
var oee = _pl.Mongo.Filter<T>(x => x.ConcurrencyKey==key
, typeof(T).Name).OrderBy(x=> x.Timestamp).FirstOrDefault();
return oee;
}
}
MongoDb层
public IEnumerable<T> Filter<T>(System.Linq.Expressions.Expression<Func<T, bool>> lambda, string collection)
{
var filter = Builders<T>.Filter.Where(lambda);
return _db.GetCollection<T>(collection).Find(filter).ToList();
}
我得到的错误是
[ERR] {document}.ComputedField is not supported.
在集合中,我看到文档在插入时已保存,但计算字段的值已正确存储,唯一的问题是当我尝试查询该字段时
问题是我查找了错误的集合并投射到错误的 class
public class TaskService<T> : ITaskService<T> where T : ITask
{
private readonly IPersistanceLayer<ObjectId, object> _pl;
public async Task<T> GetNextTask(string key)
{
var nextTask= _pl.Mongo.Filter<T>(x => x.ConcurrencyKey==key
, typeof(T).Name).OrderBy(x=> x.Timestamp).FirstOrDefault();
return nextTask;
}
}
在此方法中,T 的类型为 BaseTask 而不是 MyTask,因此我的计算字段不存在,我已更正该问题,现在可以使用了