Giter VIP home page Giter VIP logo

Comments (13)

leonardoporro avatar leonardoporro commented on May 25, 2024 1

@furier Hi, thanks for the interest in the library, and good for trying to write the mappers!
Adding support for hot chocolate makes sense. Unfortunately I'm sick now, but I can try something next weekend If I feel better
And yes, the wiki needs more work it's not 100 % completed

from detached-mapper.

furier avatar furier commented on May 25, 2024

I am playing around with implementing a TypeMapperFactory and TypeMapper

public class OptionalTypeMapperFactory : ITypeMapperFactory
{
    public bool CanCreate(Mapper mapper, TypePair typePair)
    {
        var canCreate = typePair.SourceType.IsComplex() &&
                        typeof(IOptional).IsAssignableFrom(typePair.SourceType.ClrType) &&
                        typePair.TargetType.IsPrimitive();

        return canCreate;
    }

    public ITypeMapper Create(Mapper mapper, TypePair typePair) =>
        (ITypeMapper) Activator.CreateInstance(typeof (OptionalTypeMapper<,>).MakeGenericType(typePair.SourceType.ClrType, typePair.TargetType.ClrType))!;
}

public class OptionalTypeMapper<TSource, TTarget> : TypeMapper<TSource, TTarget>
{
    private readonly PropertyInfo _isEmptyProperty;
    private readonly PropertyInfo _valueProperty;

    public OptionalTypeMapper()
    {
        var type = typeof(TSource);
        _isEmptyProperty = type.GetProperty("IsEmpty")!;
        _valueProperty = type.GetProperty("Value")!;
    }

    public override TTarget Map(TSource source, TTarget target, IMapContext context)
    {
        if (source is null || _isEmptyProperty.GetValue(source) is true)
            return target;
        
        var value = _valueProperty.GetValue(source);

        return (TTarget) Convert.ChangeType(value, typeof(TTarget))!;
    }
}

but still getting into trouble...

System.InvalidOperationException: No coercion operator is defined between types 'HotChocolate.Optional`1[System.Nullable`1[System.Guid]]' and 'System.Guid'.
   at System.Linq.Expressions.Expression.GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType)
   at System.Linq.Expressions.Expression.Convert(Expression expression, Type type, MethodInfo method)
   at System.Linq.Expressions.Expression.Convert(Expression expression, Type type)
   at Detached.Mappers.EntityFramework.Queries.QueryProvider.CreateFilterExpression[TSource,TTarget](TypePair typePair, ConstantExpression sourceConstant)
   at Detached.Mappers.EntityFramework.Queries.QueryProvider.<GetTemplate>b__6_0[TSource,TTarget](QueryCacheKey fn)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Detached.Mappers.EntityFramework.Queries.QueryProvider.GetTemplate[TSource,TTarget]()
   at Detached.Mappers.EntityFramework.Queries.QueryProvider.Load[TSource,TTarget](IQueryable`1 queryable, TSource source)
   at Detached.Mappers.EntityFramework.EFMapContext.TrackChange[TTarget,TSource,TKey](TTarget entity, TSource source, TKey key, MapperActionType actionType)
   at Detached.Mappers.TypeMappers.Entity.Complex.RootEntityTypeMapper`3.Map(TSource source, TTarget target, IMapContext context)
   at Detached.Mappers.TypeMappers.TypeMapper`2.Map(Object source, Object target, IMapContext context)
   at Detached.Mappers.Mapper.Map(Object source, Type sourceClrType, Object target, Type targetClrType, IMapContext context)
   at Detached.Mappers.EntityFramework.EFMapper.Map[TEntity](DbContext dbContext, Object entityOrDTO, MapParameters parameters)
   at Detached.Mappers.EntityFramework.EFMapper.<>c__DisplayClass8_0`1.<MapAsync>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at Gateway.API.Mutations.ProjectMutations.CreateProjects(GatewayDbContext gatewayDbContext, CreateProjectDto[] dtos, CancellationToken cancellationToken) in C:\dev\Connected\src\Gateway\Gateway.API\Mutations\ProjectMutations.cs:line 21

from detached-mapper.

furier avatar furier commented on May 25, 2024

The mapper appears to function properly; however, the issue arises when the library attempts to query for existing entities and tries to extract the key from the DTOs Id property, which is of type Optional. It is unable to coerce this into the appropriate type for the entity's Id property.

from detached-mapper.

leonardoporro avatar leonardoporro commented on May 25, 2024

Mmm.. in that case, we need to be sure that there is a factory mapper between T and Optional<T> that works in two ways
The mapper tries to convert Id types of it doesn't match
Btw you are welcome to add your changes as a part of the lib
And sorry I can't do more for you at this moment, I feel like s***, but excited that people is playing with this.

from detached-mapper.

furier avatar furier commented on May 25, 2024

First of all, I hope you get well soon! Your health is the most important thing right now, so please take your time to recover.

I appreciate your feedback and the opportunity to contribute to the library. Regarding the addition of this code, I was wondering if you think it would be more appropriate to include this functionality as part of the main library or as a separate NuGet package? This way, users could choose to add support for HotChocolate if needed, without affecting those who don't require it.

Please let me know your thoughts on this when you're feeling better, and there's absolutely no rush. Your well-being comes first.

Take care and get well soon!

from detached-mapper.

leonardoporro avatar leonardoporro commented on May 25, 2024

@furier thanks for your kind message!

Yup, Detached.Mappers.HotChocolate makes sense, to keep core clean of references.
You are welcome to put it in this repo with your name in the copyright of the project, or in your own repo.
(I can approve the pr or give you more access)
Having the code and tests over there makes easier for me to take a look if there are bugs.
And, there is a Partial Updates page in the wiki, it was meant to describe dtos, Ipatch and Optional fits perfectly there
I can add docs later with the proper credits to you in the wiki and main readme.

from detached-mapper.

leonardoporro avatar leonardoporro commented on May 25, 2024

@furier Did this work? do you need any extra help?
Also, are you planning to push something about Optional<>? Otherwise I'll create a ticket to implement it later
Thanks

from detached-mapper.

furier avatar furier commented on May 25, 2024

@leonardoporro it currently seem to work, have not picked up any issues with it yet.

however as mentioned before I did convert my DTOs Id property to no longer be "nullable" with the ? operator but are still nullable because they are wrapped in the Optional<T> type. It just has to do with the hotchocolate schema inference, that at least in previous versions it would label types wrapped in optional as not optional without the ? operator, but seems like they have fixed that in later versions.

I was planning on pushing some changes but right now I have to much going on privately and at work, I am just swamped. I am sorry, id like to contribute... but it will have to wait.

from detached-mapper.

leonardoporro avatar leonardoporro commented on May 25, 2024

@furier Totally understand you! There is no time for anything. I keep adding things to this lib just because I love it, at a cost of sacrificing other things.
There is no hurry, you may do it whenever you want, no one else asked for this.
You may also push a branch as-is, or send them by email and I will take care of integration and properly credit you.

from detached-mapper.

furier avatar furier commented on May 25, 2024

Added a PR #78

from detached-mapper.

leonardoporro avatar leonardoporro commented on May 25, 2024

@furier Awesome, thank you!

I found an issue, that is probably also the the cause of your Optional<Nullable<T>>.

When mapping Optional<T1> to Optional<T2> a recursive mapping from T1 to T2 is needed, even if T1 and T2 are of the same type.

NullableTypeMapper is doing that...

For nullable types, there won't be a ton of issues if you let the system cast or convert types, but in your case, Optional<T> when T is an entity, the mapping will fail, because the mapper copies the values from a DTO (can be the same entity or not) to an already attached entity.

The conversion will fail if T1 and T2 are different, or SaveChangesAsync will fail because the entity state will be detached.

Anyway, awesome contribution! I love it. If you make an update let me know otherwise I will do the fix later.

And I'll probably have to move your code to a new project to remove HotChocolate reference from the core mapper library (as you already mentioned before)

Thanks!

from detached-mapper.

leonardoporro avatar leonardoporro commented on May 25, 2024

Released https://www.nuget.org/packages/Detached.Mappers.HotChocolate/7.0.1
more work is needed anyway...

from detached-mapper.

leonardoporro avatar leonardoporro commented on May 25, 2024

credits

https://github.com/leonardoporro/Detached-Mapper/wiki/Partial-Updates

from detached-mapper.

Related Issues (20)

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.