2017-03-02 2 views
0

새 드라이버를 사용하기 위해 이전 레거시 MongoDB 드라이버의 일부 코드를 이식하고 있으며 문제가 발생했습니다. 공통 기본 클래스의 여러 파생 된 형식을 포함하는 컬렉션이 있습니다. 이전에는 파생 클래스 속성을 사용하여 컬렉션 (기본 형식을 사용하여 선언 된)을 쿼리하고 파생 클래스 문서를 검색 할 수있었습니다. 그래서 이러한 클래스를 제공 : 잘 작동MongoDB C# 드라이버를 사용하여 파생 형식 값 쿼리

MongoCollection<Animal> animals = db.GetCollection<Animal>("Animals"); 
var q = Query<Cat>.EQ(c => c.LikesFish, true); 
var catsThatLikeFish = animals.FindAs<Animal>(q).ToList(); 

:

[BsonDiscriminator(RootClass = true)] 
[BsonKnownTypes(typeof(Cat),typeof(Dog))] 
class Animal 
{ 
    [BsonId(IdGenerator = typeof(StringObjectIdGenerator))] 
    public string Id { get; set; } 

    public string Name { get; set; } 
} 

class Cat : Animal 
{ 
    public bool LikesFish { get; set; } 
} 

class Dog : Animal 
{ 
    public string FavouriteBone { get; set; } 
} 

나는 다음과 같은 일을 할 수 있습니다.

지금 그러나 나는 필터를 입력 할 필요가 더 이상 컴파일 할 수 없습니다 :

IMongoCollection<Animal> animals = db.GetCollection<Animal>("Animals"); 
var query = Builders<Cat>.Filter.Eq(c => c.LikesFish, true); 
var catsThatLikeFish = animals.FindSync(query); 

을이 오류 얻을 : 새로운 드라이버를 사용 가능한 더 이상

Error CS0411 The type arguments for method 'IMongoCollection<Animal>.FindSync<TProjection>(FilterDefinition<Animal>, FindOptions<Animal, TProjection>, CancellationToken)' cannot be inferred from the usage. Try specifying the type arguments explicitly. 

이인가를? 이 컬렉션의 일반적인 쿼리를 허용하는 클래스가 있으며 지금 당장은 우아한 방법을 볼 수 없습니다.

편집 :

슬프게도 별도의 컬렉션은 우리가 같은 쿼리를 사용하여 다른 유형을 끌어 필터 식을 혼합 같은 비 스타터입니다. 위의이 같은 "개와 고양이"의 예에서 :

var catQuery = Query<Cat>.EQ(c => c.LikesFish, true); 
var dogQuery = Query<Dog>.EQ(c => c.FavouriteBone, "Beef"); 
var q = Query.Or(catQuery, dogQuery); 

var catsThatLikeFishOrDogsThatLikeBeef = animals.FindAs<Animal>(q).ToList(); 

나는 "nameof"방법 위에서 살펴 보겠습니다 - 작동 할 수 있지만 나에게 옛날 방식의 우아함이 부족한 것 같다. ..

많은 도움을 주셨습니다.

감사합니다,

스티브

+1

아래의 Maksim의 답변 외에도 새로운 API에는 OfType() 메서드가 있습니다. IMdogs = db.GetCollection ("동물") OfType (). –

답변

3

당신은 togetehr 개와 고양이의 컬렉션을 가지고 있고 당신은 고양이를 필터링하려면? 아니면 모든 개와 물고기처럼 그 고양이 만 먹고 싶니?

은 첫 번째 경우에는 내가 쿼리 컬렉션에서 유일한 고양이 또는 만 개에 제안 :

var collectionAsCats = db.GetCollection<Cat>("Animal"); 
var collectionAsDogs = db.GetCollection<Dog>("Animal"); 

var catsDoesntlikeFish = collectionAsCats.Find(c => c.LikesFish == false).ToList(); 
var dogs = collectionAsDogs.Find(c => c.FavouriteBone == "bla").ToList(); 

또는 동물의 하나 개의 컬렉션이 문자열을 사용하여 데이터를 조회 할 수있다 :

var collectionAll = db.GetCollection<Animal>("Animal"); 
var filter = Builders<Animal>.Filter.Eq(nameof(Cat.LikesFish), false); 
var catsDoesntlikeFish = collectionAll.Find(filter).As<Animal>().ToList(); 

개를 함께 받으려면 고양이와 함께이 필터를 확장 할 수 있습니다.

여기 크레이그 윌슨에서 댓글을 추가

210

var collectionAll = db.GetCollection<Animal>("Animal"); 
var filter = Builders<Animal>.Filter.Eq(nameof(Cat.LikesFish), false); 
var exists = Builders<Animal>.Filter.Exists(nameof(Cat.LikesFish), false); 
var orFilter = Builders<Animal>.Filter.Or(filter, exists); 
var catsDoesntlikeFishAndDogs = collectionAll.Find(orFilter).ToList(); 

편집은 매우 관심 정보 (감사, 크레이그) : 새로운 API에

OfType() 방법이있다 ...

IMongoCollection<Dog> dogs = db.GetCollection<Animal>("Animals").OfType<Dog>() 
0

확인이 제대로 작동 않습니다 : 내가 생각하지만

var catQuery = Builders<Animal>.Filter.Eq(nameof(Cat.LikesFish), true); 
var dogQuery = Builders<Animal>.Filter.Eq(nameof(Dog.FavouriteBone), "Beef"); 
var query = Builders<Animal>.Filter.Or(catQuery, dogQuery); 
var catsThatLikeFishOrDogsThatLikeBeef = animals.FindSync(query).ToList(); 

은 이전 드라이버 방식의 우아함이 부족하다.

+1

정확히 내가 제안한 해결책은 무엇입니까? –

+0

아무 것도 잘못되었습니다. 확인 된 해결책으로이 특정 답변을 게시했습니다. 도움을 주셔서 감사합니다. –