2012-04-23 4 views
1

Mongoと公式C#ドライバを使用するアプリケーションをビルドしています。私はインターフェイスとジェネリック型の制約を使用するときに奇妙な問題を抱えています。以下を考慮してください:MongoDB C#ドライバがLINQで例外をスローする

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(...)の呼び出しとは別に、すべて正常に動作します。オフラインドライバを使用して、SelectQuery.csのprivate BsonSerializationInfo GetSerializationInfoMember(IBsonSerializer serializer, MemberExpression memberExpression)関数のvar memberSerializationInfo = containingSerializationInfo.Serializer.GetMemberSerializationInfo(memberName);コールからのnull参照例外が発生します。

私はLINQのためFluentMongoの使用に切り替える場合は、私は

を言ってメッセージを取得するには、「ディスクリミネータは、クラスだけのためではなく、インタフェースMyLib.Services.IRepoDataのために登録することができます。」

これは基本的にこの男と同じである:

FluentMongo throwing error all of a sudden

私はそれがIMongoObjectが何であるかを知っているdoesntのため、モンゴドライバが不平を言っていることを理解しています。私が理解できないのは、どこの呼び出し内の式が "o"をIMongoObject型(MongoObject型ではない)と見なしているのか(これはデバッガで確認されています。

抽象基本クラスを使用すると、すべて正常に動作します。すべてではない「MongoObjects」

おかげ

答えて

0

をので、問題は実際にC#コンパイラは、オブジェクトのための式ツリーを一緒に入れている方法であるので、私はこれを行うにはどのようないけません。型の制約のため、NameプロパティにアクセスするときにMongoObjectをIMongoObjectにキャストしています。したがって、IMongoObjectは式の型であり、私たちはIMongoObjectのメンバーを見つけることができません。次のバージョンのドライバでこのような状況でできることがあるかどうかを見ていきますが、今は抽象クラスに固執します。

「ドメイン」オブジェクトとDTOを混在させない方がよい場合があります。代わりに、2つの責任とそれぞれの責任のために1つを持ってください。

--UPDATE_ 興味深いメモ。どうやら、これはVB.NETが表現木をc#とは異なる方法で作成する方法とは異なる問題に基づいて修正されています。近い将来、これは正しく動作します。あなたはこれを証明しているテストをここに見ることができます:https://github.com/craiggwilson/mongo-csharp-driver/commit/153b9862b122521eee681a86e56806d94fed8b21#diff-1

+0

返信いただきありがとうございます。コンパイラがIMongoObjectに変換する必要性をどのように感じるかは、実際のTの型を明確に知っていて、TがIMongoObjectを実装しているときに、その奇妙な点はどうか。興味のないところでは、Tにexplicateキャストを加えて、(((MongoObject)(IMongoObject))).Nameに変換する式に追加しようとしました。役に立った; o)。上記のコードは問題をデモするための例に過ぎず、実際のコードには2つのオブジェクトツリーがあります。私は修正のリリースを見守ります。ありがとう。 – didster

関連する問題