[英]C# mongodb driver throwing System.InvalidOperationException on linq query with OrderByDescending
[英]MongoDB C# driver throwing an exception with LINQ
我正在构建一个使用Mongo和官方C#驱动程序的应用程序。 使用接口和通用类型约束时,我遇到了一个奇怪的问题。 考虑以下:
interface IMongoObject
{
BsonObjectId Id { get; set; }
string Name { get; set; }
}
class MongoObject : IMongoObject
{
public BsonObjectId Id { get; set; }
public string Name { get; set; }
}
class Program
{
MongoServer m_db;
string m_dbName;
protected void Save<T>(T entity) where T : IMongoObject
{
GetDatabase().GetCollection<T>(typeof(T).Name).Save(entity);
}
protected T Get<T>(string name) where T : IMongoObject
{
Type t = typeof(T);
// Throws
return GetDatabase().GetCollection<T>(typeof(T).Name).AsQueryable().Where(o => o.Name == name).FirstOrDefault();
}
protected MongoDatabase GetDatabase()
{
if (m_db == null)
{
var conString = "mongodb://localhost/MongoTest";
MongoUrl url = new MongoUrl(conString);
m_dbName = url.DatabaseName;
m_db = MongoServer.Create(url);
}
return m_db.GetDatabase(m_dbName);
}
void Run()
{
MongoObject o = new MongoObject();
o.Name = "Foo";
Save(o);
MongoObject b = Get<MongoObject>("Foo");
Console.ReadKey();
}
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
}
除了对Get(...)的调用外,其他所有操作都正常。 使用官方驱动程序,我从调用var memberSerializationInfo = containingSerializationInfo.Serializer.GetMemberSerializationInfo(memberName);
获取空引用异常var memberSerializationInfo = containingSerializationInfo.Serializer.GetMemberSerializationInfo(memberName);
在SelectQuery.cs中的private BsonSerializationInfo GetSerializationInfoMember(IBsonSerializer serializer, MemberExpression memberExpression)
函数中。
如果我切换为对LINQ使用FluentMongo,则会收到一条消息,说
“辨别器只能为类注册,不能为接口MyLib.Services.IRepoData注册。”
这和这个家伙基本相同:
我知道Mongo驱动程序在抱怨,因为它不知道IMongoObject是什么。 我不明白的是为什么where调用中的表达式将IMongoObject类型视为“ o”而不是MongoObject类型(与调试器确认,这是发生了什么),这就是事实。
如果我切换为使用抽象基类,则一切正常。 我不做什么,因为不是所有的“ MongoObjects”
谢谢
因此,问题实际上在于C#编译器如何将对象的表达式树放在一起。 由于类型限制,在访问Name属性时,它将MongoObject强制转换为IMongoObject。 因此,IMongoObject是表达式的类型,我们在IMongoObject上找不到任何成员。 我将在下一个版本的驱动程序中查看是否可以针对这种情况做些什么,但就目前而言,我将坚持使用抽象类。
另外,最好不要将“域”对象与DTO混合使用。 而是为每个职责分配2个,并在每个职责之间进行映射。
-更新-有趣的笔记。 显然,这是基于另一个问题解决的,该问题与VB.NET如何创建与c#不同的表达式树有关。 因此,在不久的将来,这将正常工作。 您可以在此处查看证明这一点的测试: https : //github.com/craiggwilson/mongo-csharp-driver/commit/153b9862b122521eee681a86e56806d94fed8b21#diff-1 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.