Reputation: 1594
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
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