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 (...). Используя официальный драйвер, я получаю исключение нулевой ссылки из вызова var memberSerializationInfo = containingSerializationInfo.Serializer.GetMemberSerializationInfo(memberName); в функции private BsonSerializationInfo GetSerializationInfoMember(IBsonSerializer serializer, MemberExpression memberExpression) в SelectQuery.cs.

Если я перейти на использование FluentMongo для LINQ, я получаю сообщение о том,

«Дискриминаторы могут быть зарегистрированы только для классов, а не для интерфейса MyLib.Services.IRepoData.»

Это в основном так же, как этот парень:

FluentMongo throwing error all of a sudden

Я понимаю, что водитель Монго жалуется, потому что он не знает, что IMongoObject есть. То, что я не понимаю, - это то, почему выражение внутри вызываемого вызова видит «о» как тип IMongoObject, а не типа MongoObject (подтвержденный отладчиком, это то, что происходит), что и есть.

Если я переключусь на использование абстрактного базового класса, все работает отлично. Я не то, что делать это, потому что не все «MongoObjects»

Благодарности

ответ

0

Итак, вопрос на самом деле заключается в том, как C# компилятор воедино дерево выражения для объекта. Из-за вашего ограничения типа он бросает ваш MongoObject в IMongoObject при доступе к свойству Name. Следовательно, IMongoObject является типом выражения, и мы не можем найти каких-либо членов в IMongoObject. Я посмотрю, есть ли что-то, что мы можем сделать для этого обстоятельства в следующей версии драйвера, но пока я придерживаюсь абстрактных классов.

В отдельном примечании, возможно, лучше не смешивать объекты домена с вашими DTO. Вместо этого имейте 2, по одному за каждую ответственность и карту между ними.

--UPDATE-- Интересное примечание. По-видимому, это было исправлено на основе другой проблемы с тем, как VB.NET создает деревья выражений по-разному, что C#. Таким образом, в ближайшем будущем это будет работать правильно. Вы можете увидеть тест, подтверждающий это здесь: https://github.com/craiggwilson/mongo-csharp-driver/commit/153b9862b122521eee681a86e56806d94fed8b21#diff-1.

+0

большое спасибо за ответ. Его странно, как компилятор чувствует необходимость конвертировать в IMongoObject, когда он четко знает фактический тип T и что T реализует IMongoObject. Из интереса я попытался добавить экспликативный прилив к T в выражение, которое он преобразует в (((MongoObject) (IMongoObject)) o) .Name. Полезно; o). Разделение WRT проблем, приведенный выше код был просто примером демонстрации проблемы - фактический код имеет 2 дерева объектов, как вы предлагаете. Я буду следить за выпуском исправления. Благодарю. – didster

Смежные вопросы