0

I need to construct a query using as a FilterDefinition an explicit Interface but it throws an exception saying :

System.InvalidOperationException
  Message={document}.Pointer is not supported.
  Source=MongoDB.Driver

I have tried this with normal Interface implementation and it works as expected. But I need to implement an Interface explicitly as I'm having 2 interfaces with the same property names as shown in the code below:

    public class Offer : OfferBase, IPointerTo<ServiceCategory>, 
    IPointerTo<Company>
    {       
        [BsonElement("_p_ServiceCategoryObj")]
        [JsonProperty("serviceCategoryObj")]
        string IPointerTo<ServiceCategory>.Pointer { get; set; }

        [BsonElement("_p_companyObj")]
        [JsonProperty("companyObj")]
        string IPointerTo<Company>.Pointer { get; set; }       

    }

So, I create a FilterDefinition that I will use in a Find. As I mentioned before, this works fine if it were not an explicit interface implementation. For instance: if just use one of them normally implemented and the other explicitly it will work when querying for the normal one. But having the above code constraints and creating the filter like this:

    FilterDefinition<Offer> innnerFilter = MongoQueryBuilder.AddFilter<Offer> 
    (offer =>string.IsNullOrEmpty((offer as 
    IPointerTo<ServiceCategory>).Pointer));  

So when the Find with that filter is being executed the exception stated above is being thrown.

Note: MongoQueryBuilder.AddFilter is just a wrapper that I did to make it easier but that it's not the issue as all the other queries work fine using that.

I would expect to get the results as I get them when just having one of the interfaces implemented normally and querying with that Interface member but in my current scenario I need to have them both implemented and thus they must be implemented explicitly.

I may not be doing something properly or using it as I should but I haven't been to find any solution to this.

Edit: (thanks to @Lakerfield answer)

I was not able to find Pointer as I was asking for Offer and as Pointer it's an explicit interface it was not being able to publicly find it. So, I was able to solve it like this:

 public class Offer : OfferBase, IPointerTo<ServiceCategory>, IPointerTo<Company>
    {
        [BsonIgnoreIfNull]
        [BsonIgnoreIfDefault]
        [BsonElement("_p_ServiceCategoryObj")]
        [JsonProperty("serviceCategoryObj")]
        public string ServiceCategoryPointer
        {
            get => (this as IPointerTo<ServiceCategory>).Pointer;
            set => (this as IPointerTo<ServiceCategory>).Pointer = value;
        }

        [BsonIgnore]
        string IPointerTo<ServiceCategory>.Pointer { get; set; }

        [BsonIgnoreIfNull]
        [BsonIgnoreIfDefault]
        [BsonElement("_p_companyObj")]
        [JsonProperty("companyObj")]
        public string CompanyPointer
        {
            get => (this as IPointerTo<Company>).Pointer;
            set => (this as IPointerTo<Company>).Pointer = value;
        }

        [BsonIgnore]
        string IPointerTo<Company>.Pointer { get; set; }

And then doing the query like this: (Now I'm use Linq instead of FilterDefinition but that is not relevant for the sake of this solution)

 private static Expression<Func<Offer, bool>> InnerQueryServiceCategory(string serviceCategoryId)
 {
    return offer => (offer.IsDeleted == false || !offer.IsDeleted.HasValue) && offer.ServiceCategoryPointer == PointedCollections.ServiceCategoryCollection.GetDescription() + serviceCategoryId;
 }

offer.ServiceCategoryPointer is publicly available and it's a member of Offer.

Sebastian Inones
  • 1,561
  • 1
  • 19
  • 32

1 Answers1

1

The problem is the duplicate Pointer property name. In MongoDB a object must have unique propertynames.

Workaround just use two seperate properties with different names, forward your explicit interfaces to those, and use the new properties in your query.

public class Offer : OfferBase, IPointerTo<ServiceCategory>, IPointerTo<Company> 
{ 
  public string ServiceCategoryPointer { get; set; } 
  public string CompanyPointer { get; set; }

  string IPointerTo<ServiceCategory>.Pointer 
  { 
    get => ServiceCategoryPointer; 
    set => ServiceCategoryPointer = value;
  } 
  string IPointerTo<Company>.Pointer
   { 
    get => CompanyPointer; 
    set => CompanyPointer = value;
  } 
}
Lakerfield
  • 1,071
  • 1
  • 7
  • 19
  • You are right on duplicate **Pointer** property Name. Sorry about my misleading question. As I tried to post a minimal, complete and verifiable example I mistakenly omit some attributes which I will now add to the original question. Now, thanks tor your answer I've realized that is not being able to find .**Pointer** as I'm asking for **Offer** and as it's an explicit interface is not being able to publicly find it. – Sebastian Inones Aug 08 '19 at 08:50
  • Just removed my update about a custom serializer from the answer. That works for saving but not for querying. I think the above solution still works, when you attach the attributes to the public properties. – Lakerfield Aug 13 '19 at 10:31