ShamilS
ShamilS

Reputation: 1594

.NET6/EF: The best overloaded method match for 'Microsoft.EntityFrameworkCore.DbSet<...>.Add(...)' has some invalid arguments

I'm working on a generic code to add .NET 6 Entity Framework DbSet<...> records, deserialized from JSON strings. The original code is (much) more elaborated, below are just samples to demonstrated the issue - the following method:

public static void AddRecord(dynamic dbSet, Type entityType, string json)
{
    var dataRecord = System.Text.Json.JsonSerializer.Deserialize(json, entityType);
    dbSet.Add(dataRecord);
}

results in a run-time error at dbSet.Add(dataRecord) call:

"The best overloaded method match for
'Microsoft.EntityFrameworkCore.DbSet<Northwind.Models.Category>.Add
(Northwind.Models.Category)' has some invalid arguments"}
...
This exception was originally thrown at this call stack:
System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2<T0, T1>
(System.Runtime.CompilerServices.CallSite, T0, T1)

if you call it, e.g., this way:

using (var ctx = ...)
{
  ...
  var json = ...
  ...
  AddRecord(ctx.Categories, typeof(Category), json);
}

I have intentionally, for clarity, used in the above code concrete dbSet (ctx.Categories) and compile time typedef (typeof(Category)) - in actual code these are run-time defined variables.

If you "unroll" the method code and write it this way:

using (var ctx = ...)
{
  ...
  var json = ...
  ...
  var dataRecord = System.Text.Json.JsonSerializer.Deserialize(json, typeof(Category));
  ctx.Categories.Add(dataRecord);
}

you would still get the mentioned above run-time error for the .Add method.

But if you write:

  var dataRecord = System.Text.Json.JsonSerializer.Deserialize<Category>(json);
  ctx.Categories.Add(dataRecord);

or

  var dataRecord = System.Text.Json.JsonSerializer.Deserialize(json);
  ctx.Categories.Add((Category)dataRecord);

the code will work without any issues.

Finally, an attemp to use Convert.ChangeType doesn't help:

  var dataRecord = System.Text.Json.JsonSerializer.Deserialize(json);
  ctx.Categories.Add(Convert.ChangeType(dataRecord, typeof(Category)));

So, it looks like an explicit object type casting is compiled to and makes on rum-time some "special object interfaces arrangements", which dynamic object type casting doesn't?

[Update]

Okan Karadag's prompt answer below gave me a hint how to change AddRecord(...) method to workaround the subject issue:

public static void AddRecord(DbContext dbContext, Type entityType, string json)
{
    var dataRecord = System.Text.Json.JsonSerializer.Deserialize(json, entityType);
    dbContext.Add(dataRecord);
}

This method works flawlessly. Although it doesn't answer the subject question, why the original AddRecord(...) method

public static void AddRecord(dynamic dbSet, Type entityType, string json)
{
    var dataRecord = System.Text.Json.JsonSerializer.Deserialize(json, entityType);
    dbSet.Add(dataRecord);
}

results in 'The best overloaded method match for 'Microsoft.EntityFrameworkCore.DbSet<...>.Add(...)' has some invalid arguments...' runtime error at

   dbSet.Add(dataRecord);

code line.

Upvotes: 0

Views: 124

Answers (1)

Okan Karadag
Okan Karadag

Reputation: 3055

You can use generic for dynamic.

public void AddEntity<T>(string json) where T:class
{
    var entity = JsonSerializer.Deserialize<T>(json);
    ArgumentNullException.ThrowIfNull(entity);
    dbContext.Add<T>(entity);
    dbContext.SaveChanges();
}

You can see link for problem error.

Upvotes: 1

Related Questions