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

Auditing Where extension method throws exception #653

Open
Nate129 opened this issue Nov 23, 2020 · 4 comments
Open

Auditing Where extension method throws exception #653

Nate129 opened this issue Nov 23, 2020 · 4 comments
Assignees

Comments

@Nate129
Copy link

Nate129 commented Nov 23, 2020

Description

I am unable retrieve audit entries for a generic type using the Where<T>() extension method.

Exception

System.Exception
Unhandled exception. System.Exception: Oops! The number of argument for the key specified doesn't match with the number of key members. Please report the issue including the stack trace to our support team: info@zzzprojects.com
   at Z.EntityFramework.Plus.AuditExtensions.Where[TAuditEntry,T](DbSet`1 set, Object[] keyValues)
   at Z.EntityFramework.Plus.AuditExtensions.Where[T](DbSet`1 set, Object[] keyValues)

Fiddle or Project

https://dotnetfiddle.net/bEDZTU

Further technical details

  • EF version: EF Core 5
  • EF Plus version: 5.1.2
  • Database Provider: Sqlite (also happens using Sql Server in fiddle)
@Nate129
Copy link
Author

Nate129 commented Nov 23, 2020

I also experienced the issue on EF Core 3.1.10 (latest before 5) and equivalent EF Plus version (3.1.2).

@JonathanMagnan
Copy link
Member

Thank you for the project @nwhittle ,

We will look at it.

Best Regards,

Jon


Performance Libraries
context.BulkInsert(list, options => options.BatchSize = 1000);
Entity Framework ExtensionsEntity Framework ClassicBulk OperationsDapper Plus

Runtime Evaluation
Eval.Execute("x + y", new {x = 1, y = 2}); // return 3
C# Eval FunctionSQL Eval Function

@JonathanMagnan JonathanMagnan self-assigned this Nov 23, 2020
@JonathanMagnan
Copy link
Member

Hello @nwhittle ,

Sorry for the long waiting,

Unfortunately retrieving the audit with the Where method doesn't work as you want.

See: https://entityframework-plus.net/ef-core-audit-retrieve-audit-entries-for-specific-item

You can either pass an item or the key:

using (var ctx = new TestContext())
{
    ctx.AuditEntries.Where(item);
    ctx.AuditEntries.Where<Entity_Basic>(item.ID);
    ctx.AuditEntries.Where<Entity_Basic>(101);
}

If you wish to return all items for a specific type, here is an online example: https://dotnetfiddle.net/bZdD0q

var customers = context.AuditEntries.Where(x => x.State == AuditEntryState.EntityAdded && x.EntityTypeName == "Customer").ToList();

(I also added the AutoSavePreAction which was missed from your example)

Let me know if that helped you.

Best Regards,

Jon

@Nate129
Copy link
Author

Nate129 commented Dec 1, 2020

Hi @JonathanMagnan,

Thank you for your reply. My goal (as you correctly determined) was to retrieve all entries for a type without retrieving any of that type's entities from the database first, so the first link you provided doesn't seem relevant for my use case.

I initially wrote a query like the one you suggested to accomplish my goal, but then I went to use the generic type argument I had available, i.e:

var customers = context.AuditEntries.Where(x => x.State == AuditEntryState.EntityAdded && x.EntityTypeName == typeof(T).Name).ToList();

I concluded that this must be the incorrect way to query the entries by type because EF Plus sets the x.EntityTypeName internally when creating the entries and as such would, for the purpose of api design consistency, resolve generic types internally as well since the strategy for storing the name of a given type is 'hidden away' from the user. If EF Plus did not resolve them internally, then users would then be left to guess by testing to figure out which strategy EF Plus used to store the name of the entity class, i.e. typeof(T).Name, typeof(T).FullName, or typeof(T).FullyQualifiedName, etc.

I believe this is the primary reason I expected the generic Where<T>() extension method to support the type of query I was trying to use it for- I was expecting to find some method to allow EF Plus to resolve my generic type argument for me since it did so when creating the entry internally.

Since I seem to have found an alternative which allows me to continue using the auditing feature (although my code won't be as concise), I consider myself unblocked and will continue using EF Plus for my project.

Perhaps I could provide some feedback, given my thought process when learning the EF Plus api:

  • If the Where<T> is working as intended, then it would seem that a more specific exception would help fortify the api against misuse- the one I received seemed to be a fallback exception, which made me think I had encountered a bug
  • It would seem, given the previous point as the final strategy for improving the product, that the documentation could use an update to more accurately reflect the intended usages of the Where<T> extension method- I interpreted it to be a convenience method to interact with entries for a generic type, which it turns out is a broader scope than it actually seems to be
  • Going further, perhaps the api could be updated to also provide a method or methods or update the Where<T> method to resolve the type names for a generic types for the user- it does so internally when creating the entries so it would seem like the same would be expected when querying the entries. It seems to me that it's not a good experience for the user to have to guess which strategy EF Plus used internally to generate the type name for the entry

I will leave the issue open in case my feedback should be represented as an open issue. If this is not appropriate I can close it since I am unblocked.

Thanks,

Nathan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants