Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CosmosDb] select on ID is not selecting on ID but evaluating on clientside #14934

Closed
Mortana89 opened this issue Mar 6, 2019 · 3 comments
Closed
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported

Comments

@Mortana89
Copy link

Mortana89 commented Mar 6, 2019

I have an entity as follows;

public class B : A
{
 public string ExternalIdentifier { get; set; }    
}

public abstract class A
{
        [NotMapped]
        [JsonIgnore]
        public string Id
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }

        [Key]
        [JsonProperty(PropertyName = "id")]
        [DataMember(Name = "id")]
        protected string id;
}

When executing a query like _context.Bs.SingleOrDefault(x => x.Id == 'blabla'), I notice, when debugging very deeply, that the ID parameter is not being resolved on database side.

Immediately two concerns here:

  • Why am I not getting a warning that this is being evaluated on clientside
  • Why is Id not being resolved to the cosmos-db specific id field?

The reason why I added all those things just to map Id successfully, is because cosmos DB already has an 'id' property on a document. But I don't want to see 'id' as a public property as that's nasty, I wanted it camelcase. However, when first adding the camelcase Id that referenced the id field, the Id field was getting saved in the db as well, which is even crazier, we already have an id!

I'm thinking the NotMapped attribute is causing the property not being resolved.
This resolving is happening in the MemberAccessExpressionVisitor.GetPropertyPath, to be more precise, this piece of code returns null for the 'Id' property:

            var property = propertyName == null
                ? null
                : (IPropertyBase)entityType.FindProperty(propertyName);

This is causing it to just download the whole collection and iterate in memory. Pretty fast I was getting throttled :(

Using the latest 2.2 release btw

@smitpatel
Copy link
Member

I'm thinking the NotMapped attribute is causing the property not being resolved.

That is the reason. Remove NotMapped. When you put NotMapped, you are effectively telling EF that don't store this property in database. When EF encounter such property in LINQ query, EF will materialize the whole object to run the query. Since it is in where predicate, it will fetch whole container data from server. Cosmos is still in preview and does not have enough logging to warn for client eval.

when first adding the camelcase Id that referenced the id field, the Id field was getting saved in the db as well, which is even crazier, we already have an id!

Use this
modelBuilder.Entity<A>().Property(e => e.Id).Metadata.Cosmos().PropertyName = "id";

@smitpatel smitpatel added the closed-no-further-action The issue is closed and no further action is planned. label Mar 6, 2019
@Mortana89
Copy link
Author

I'm thinking the NotMapped attribute is causing the property not being resolved.

That is the reason. Remove NotMapped. When you put NotMapped, you are effectively telling EF that don't store this property in database. When EF encounter such property in LINQ query, EF will materialize the whole object to run the query. Since it is in where predicate, it will fetch whole container data from server. Cosmos is still in preview and does not have enough logging to warn for client eval.

when first adding the camelcase Id that referenced the id field, the Id field was getting saved in the db as well, which is even crazier, we already have an id!

Use this
modelBuilder.Entity<A>().Property(e => e.Id).Metadata.Cosmos().PropertyName = "id";

Thanks! Is it possible to use an annotation instead of doing this with the modelbuilder?
It's a base class so would save me many plumbing :)

@smitpatel
Copy link
Member

It is not possible to do this currently with annotations. But that is in plan. See #12086 for more details.

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported
Projects
None yet
Development

No branches or pull requests

3 participants