Giter VIP home page Giter VIP logo

efcorejsonvalueconverter's People

Contributors

alexengblom avatar jukkahyv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

efcorejsonvalueconverter's Issues

Property with HasJsonConversion on owned entity always sent as database Update if owned entity is replaced

I'm not sure if this is an issue with the library or EF Core itself, but it may be worth being aware of at least.

If you use HasJsonConversion()on a property of an owned type and you replace the owned type (e.g. because you're using immutable value objects, so you cannot modify the properties directly), the Json property is always recognized as a change even if its property value is the same as the original so the field is always included in an update to the database (I'm using SQL Server for storage).

Extremely basic example:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Entity>().Property(e => e.Items).HasJsonValueConversion();

        modelBuilder.Entity<Entity>().OwnsOne(e => e.Owned, b =>
        {
            b.Property(o => o.Items).HasJsonValueConversion();
        });
    }

    public DbSet<Entity> Entities { get; set; }
}

public class Entity
{
    public int Id { get; set; }
    public string Field { get; set; }
    public List<string> Items { get; set; }
    public Owned Owned { get; set; }
}

public class Owned
{
    public string Field { get; set; }
    public List<string> Items { get; set; }
}

Assume you already have an entity saved in the database that is equivalent to:

new Entity 
{
    Id = 1, 
    Field = "string", 
    Items = new List<string>() { "Hello", "World!" },
    Owned = new Owned
    {
        Field = "string", 
        Items = new List<string>() { "Homer", "Simpson" }
    }
};

On the root entity itself, everything works as expected when assigning an equivalent value to the property:

// not sent as update, db value is the same
entity.Items = new List<string>() { "Hello", "World!" }; 

On the owned entity, if you reassign the property without replacing the owned object itself, again everything works as expected:

// not sent as update, db value is the same
entity.Owned.Items = new List<string>() { "Homer", "Simpson" }; 

If you replace the owned entity, then the value is always considered to be modified, even though regular values (string Field) are correctly handled:

entity.Owned = new Owned
{
    // not sent as update even though owned entity is replaced, db value is the same
    Field = "string" ,
    // SENT AS UPDATE, db value is same
    Items = new List<string>() { "Homer", "Simpson" };
}

Even if you reassign the value to the exact same reference, it's still treated as modified:

var owned = entity.Owned;
entity.Owned = new Owned
{
    // not sent as update even though owned entity is replaced, db value is the same
    Field = owned.Field,
    // SENT AS UPDATE, db value is same
    Items = owned.Items 
}

It's almost like the change tracker is not taking into consideration the ValueComparer when fixing up the owned object's properties after a reassignment. Do you think there is anything the library could do to help here?

If I could find out which properties use the JsonValueComparer/JsonValueConverter while looping through ChangeTracker.Entries I could probably fix up the properties, but I don't know how to find out if a property has a ValueConverter/ValueComparer with the metadata that is available at that point. Finding the properties with a JasonValueComparer is easy enough, but the properties are not marked as modified, so I'm not sure why they are still flowing to the database update.

Primitives do not work

I get the following when having primitives (int32, bool) with [JsonField] attributes when using EF Add-Migration:

System.ArgumentException: GenericArguments[0], 'System.Int32', on 'Innofactor.EfCoreJsonValueConverter.JsonValueConverter1[T]' violates the constraint of type 'T'. ---> System.TypeLoadException: GenericArguments[0], 'System.Int32', on 'Innofactor.EfCoreJsonValueConverter.JsonValueConverter1[T]' violates the constraint of type parameter 'T'.
at System.RuntimeTypeHandle.Instantiate(Type[] inst)
at System.RuntimeType.MakeGenericType(Type[] instantiation)
--- End of inner exception stack trace ---
at System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
at System.RuntimeType.MakeGenericType(Type[] instantiation)
at Innofactor.EfCoreJsonValueConverter.ModelBuilderExtensions.AddJsonFields(ModelBuilder modelBuilder, Boolean skipConventionalEntities)
at Appva.Auth.Clients.Api.Models.ClientDbContext.OnModelCreating(ModelBuilder modelBuilder) in C:\development\auth-clients-api\src\Appva.Auth.Clients.Api\Appva.Auth.Clients.Api\Models\ClientDbContext.cs:line 27
at Microsoft.EntityFrameworkCore.Infrastructure.ModelCustomizer.Customize(ModelBuilder modelBuilder, DbContext context)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.b__7_3(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure1 accessor) at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure1 accessor)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func1 factory) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType) at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0() at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_01.b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

Can we use it for localization also?

Hi there, this is not an issue and more a question!

Do you think it is possible to use this library for localization?

I asked a question here, and I think it is possible to extend your library for this use-case!

Support ChangingAndChangedNotifications tracking strategy

Object change detection does not work with ChangeTrackingStrategy.ChangingAndChangedNotifications because JsonValueComparer is not called. JsonValueComparer is only called with ChangeTrackingStrategy.Snapshot.

Is there a way to detect changes with ChangeTrackingStrategy.ChangingAndChangedNotifications?

Entity Framework Core 6.0 (NET 6) support

After upgrading the project to NET 6 i've got:
MissingMethodException: Method not found: 'System.Type Microsoft.EntityFrameworkCore.Metadata.ITypeBase.get_ClrType()'.

Maybe, the problem is with Entity Framework Core 6

License limitations

Just wanted to say that your converter works great but unfortunately in my case I can't use it due to the license you have assigned to it. I work for a company that don't want to disclose its software products. Maybe in the near future could you please consider moving it to another one like MIT? Regards.

Support for .net standard 2.0

I was wondering why the project was upgraded to .net standard 2.1 instead of staying on 2.0?
This breaks compatibility with projects that need to support .net framework.

Ignored properties with JSON attribute are causing issues

Issue appeared after moving to use clr-types for initializing json properties without explicit entity.Property(...) calls (issue #2 ). Since call to builder.AddJsonFields initializes properties besides their valueconverters, we should filter out properties that are marked as ignored. Otherwise it will result in failed model state.

Question: Can we pass custom converters

Hi,

Thanks for a wonderful library, it makes job easier and clean code is a bonus. I have customer converters for some objects. How can we make use of it?

Thanks,
Attiqe

Customise JSON serialisation

It's possible to customise JSON serialisation at a global level by changing JsonConvert.DefaultSettings, but it would be good to have the option to customise it just for EF Core JSON serialisation by specifying a JsonSerializerSettings, for example to prevent cyclic references from being serialised, configure null handling, or to add type information to the serialised JSON to support interfaces:


var jsonSettings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
     ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    TypeNameHandling = TypeNameHandling.Objects,
    TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple
};

var json = JsonConvert.SerializeObject(obj, jsonSettings);
var obj = JsonConvert.DeserializeObject<T>>(json, jsonSettings);

At it's most basic, this could be implemented as a global setting by adding a static JsonSerializerSettings in this library (or a configuration class that composes it). I imagine a global setting would be what most people would want.

Alternatively (or additionally), the HasJsonValueConversion extension method could have an optional JsonSerializerSettings argument added to it. Not sure if there would really be a need to configure it for each property though.

Do not require defining JSON properties with Property

Problem is that without the call to Property(), EF recognizes JSON fields as navigation properties instead of plain properties and tries to look for a primary key.

System.InvalidOperationException: The entity type 'Address' requires a primary key to be defined.

For now, I cannot find a way to remove the navigation property from the entity type.

Related to dotnet/efcore#11199

package not compatible with netcoreapp3.1

Package Innofactor.EfCoreJsonValueConverter 2.0.2 is not compatible with netcoreapp3.1 (.NETCoreApp,Version=v3.1).
Package Innofactor.EfCoreJsonValueConverter 2.0.2 supports: netstandard2.1 (.NETStandard,Version=v2.1).

I uninstalled the dotnet sdk and reinstalled the sdk, and then an error occurred.

net core sdk: 3.1.300
net core: 3.1.4

package not compatible with netcoreapp3.1

Package Innofactor.EfCoreJsonValueConverter 2.0.2 is not compatible with netcoreapp3.1 (.NETCoreApp,Version=v3.1).
Package Innofactor.EfCoreJsonValueConverter 2.0.2 supports: netstandard2.1 (.NETStandard,Version=v2.1).

I uninstalled the dotnet sdk and reinstalled the sdk, and then an error occurred.

net core sdk: 3.1.300
net core: 3.1.4

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.