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

Provide API for returning Func<TEntity, bool> predicated based on keys #27623

Closed
Liero opened this issue Mar 11, 2022 · 1 comment
Closed

Provide API for returning Func<TEntity, bool> predicated based on keys #27623

Liero opened this issue Mar 11, 2022 · 1 comment

Comments

@Liero
Copy link

Liero commented Mar 11, 2022

Problems I'm trying to solve

In short I want to do this:

object[] keys = ....;
dbContext.Set<TEntity>().Local.Find(keys)
//or
dbContext.ChangeTracker.Entries<TEntity>().Find(keys);

or

bool EqualsByPK(TEntity entity1,  TEntity entity2);

or

resolve duplicates as described in the change-tracking/identity-resolution docs.

In other words, find out, whether entity with specified key is already tracked:

   context.ChangeTracker.TrackGraph(entity, node =>
        {
            var entityType = node.Entry.Metadata;                
                            
            //documented way is not generic because of hard code Id property
            //var keyValue = node.Entry.Property("Id").CurrentValue; //hard coded ID
            //var existingEntity = node.Entry.Context.ChangeTracker.Entries()
            //    .FirstOrDefault(
            //        e => Equals(e.Metadata, entityType)
            //             && Equals(e.Property("Id").CurrentValue, keyValue)); //hard coded ID
            
            object[] keyValues = entityType.GetKeyValues(node.Entry.Entity); //new api
            //object[] keyValues = entityType.GetKeys()
            //    .FirstOrDefault(key => key.IsPrimaryKey())?.Properties
            //    .Select(property => node.Entry.CurrentValues[property])
            //    .ToArray();
              

            var predicate = entityType.CreatePrimaryKeyPredicate(keyValues); //new API
                .dbContext.ChangeTracker.Entries().Where(e => Equals(e.Metadata, entityType))
                .FirstOrDefault(e => predicate(e.Entity));

            var existingEntity = dbContext.ChangeTracker.Entries().FirstOrDefault(predicate);
                
            if (existingEntity == null)
            {
                Console.WriteLine($"Tracking {entityType.DisplayName()} entity with key value {keyValue}");

                node.Entry.State = EntityState.Modified;
            }
            else
            {
                Console.WriteLine($"Discarding duplicate {entityType.DisplayName()} entity with key value {keyValue}");
            }
        });

Proposed solution:

new APIs:

  1. object[] GetKeyValues(this IEntityType entityType, object Entity);

  2. Func<bool, object>(this IEntityType entityType, entityType.CreatePrimaryKeyPredicate(keyValues))

    object[] keyValues = entityType.GetKeyValues(node.Entry.Entity);
    //object[] keyValues = entityType.GetKeys()
    // .FirstOrDefault(key => key.IsPrimaryKey())?.Properties
    // .Select(property => node.Entry.CurrentValues[property])
    // .ToArray();
    var predicate = entityType.CreatePrimaryKeyPredicate(keyValues);
    dbContext.ChangeTracker.Entries().Where(e => Equals(e.Metadata, entityType))
    .FirstOrDefault(predicate);

@ajcvickers
Copy link
Member

Duplicate of #7391.

@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
Projects
None yet
Development

No branches or pull requests

2 participants