OData / odata.net

ODataLib: Open Data Protocol - .NET Libraries and Frameworks
https://docs.microsoft.com/odata
Other
685 stars 349 forks source link

Incorrect number of arguments supplied for call to method in 7.14.1 #2617

Closed premiaware closed 1 year ago

premiaware commented 1 year ago

I have update from 7.12.2 to 7.14.1 and i have this exception:

{"Incorrect number of arguments supplied for call to method 'System.Object ProjectionGetEntry(System.Object, System.String, Microsoft.OData.Client.Materialization.IODataMaterializerContext)'\r\nParameter name: method"}

" at System.Dynamic.Utils.ExpressionUtils.ValidateArgumentCount(MethodBase method, ExpressionType nodeKind, Int32 count, ParameterInfo[] pis)\r\n at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1)\r\n at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable1 arguments)\r\n at Microsoft.OData.Client.ProjectionPlanCompiler.GetDeepestEntry(Expression[] path)\r\n at Microsoft.OData.Client.ProjectionPlanCompiler.RebindEntityMemberInit(MemberInitExpression init)\r\n at Microsoft.OData.Client.ProjectionPlanCompiler.VisitMemberInit(MemberInitExpression init)\r\n at Microsoft.OData.Client.ALinqExpressionVisitor.Visit(Expression exp)\r\n at Microsoft.OData.Client.ALinqExpressionVisitor.VisitMemberAssignment(MemberAssignment assignment)\r\n at Microsoft.OData.Client.ALinqExpressionVisitor.VisitBinding(MemberBinding binding)\r\n at Microsoft.OData.Client.ALinqExpressionVisitor.VisitBindingList(ReadOnlyCollection1 original)\r\n at Microsoft.OData.Client.ALinqExpressionVisitor.VisitMemberInit(MemberInitExpression init)\r\n at Microsoft.OData.Client.ProjectionPlanCompiler.VisitMemberInit(MemberInitExpression init)\r\n at Microsoft.OData.Client.ALinqExpressionVisitor.Visit(Expression exp)\r\n at Microsoft.OData.Client.ProjectionPlanCompiler.VisitLambda(LambdaExpression lambda)\r\n at Microsoft.OData.Client.ALinqExpressionVisitor.Visit(Expression exp)\r\n at Microsoft.OData.Client.ProjectionPlanCompiler.CompilePlan(LambdaExpression projection, Dictionary2 normalizerRewrites, IODataMaterializerContext materializerContext)\r\n at Microsoft.OData.Client.Materialization.ODataEntityMaterializer.CreatePlan(QueryComponents queryComponents, IODataMaterializerContext materializerContext)\r\n at Microsoft.OData.Client.Materialization.ODataEntityMaterializer..ctor(IODataMaterializerContext materializerContext, EntityTrackingAdapter entityTrackingAdapter, QueryComponents queryComponents, Type expectedType, ProjectionPlan materializeEntryPlan)\r\n at Microsoft.OData.Client.Materialization.ODataReaderEntityMaterializer..ctor(ODataMessageReader odataMessageReader, ODataReaderWrapper reader, IODataMaterializerContext materializerContext, EntityTrackingAdapter entityTrackingAdapter, QueryComponents queryComponents, Type expectedType, ProjectionPlan materializeEntryPlan)\r\n at Microsoft.OData.Client.Materialization.ODataMaterializer.CreateMaterializerForMessage(IODataResponseMessage responseMessage, ResponseInfo responseInfo, Type materializerType, QueryComponents queryComponents, ProjectionPlan plan, ODataPayloadKind payloadKind, MaterializerCache materializerCache)\r\n at Microsoft.OData.Client.MaterializeAtom..ctor(ResponseInfo responseInfo, QueryComponents queryComponents, ProjectionPlan plan, IODataResponseMessage responseMessage, ODataPayloadKind payloadKind, MaterializerCache materializerCache)\r\n at Microsoft.OData.Client.QueryResult.CreateMaterializer(ProjectionPlan plan, ODataPayloadKind payloadKind)\r\n at Microsoft.OData.Client.QueryResult.ProcessResult[TElement](ProjectionPlan plan)\r\n at Microsoft.OData.Client.DataServiceRequest.EndExecute[TElement](Object source, DataServiceContext context, String method, IAsyncResult asyncResult)\r\n at Microsoft.OData.Client.DataServiceQuery1.EndExecute(IAsyncResult asyncResult)\r\n at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endFunction, Action1 endAction, Task1 promise, Boolean requiresSynchronization)\r\n--- End of stack trace from previous location ---\r\n at AppData.Services.DataRepository.<>cDisplayClass353_0.d.MoveNext() in C:\Work\UniversalApps\FastHomeMobile\FastHomeMobile.LogicUI\DataServices\ComuniRegioniNazioni.cs:line 336\r\n at Polly.AsyncPolicy.<>c__DisplayClass40_0.<b0>d.MoveNext()\r\n at Polly.Retry.AsyncRetryEngine.d0`1.MoveNext()\r\n at Polly.AsyncPolicy.d12.MoveNext()\r\n at AppData.Services.DataRepository.d__353.MoveNext() in C:\Work\UniversalApps\FastHomeMobile\FastHomeMobile.LogicUI\DataServices\ComuniRegioniNazioni.cs:line 305"

this is the query that is use:

from comuni in Comuni
where comuni.ID == ID
select new ComuneProvinciaBridge
{
    Comune = new ComuniBridge
    {
        ID = comuni.ID,
        Denominazione = comuni.Denominazione
    },
    Provincia = new ProvinceBridge
    {
        ID = comuni.Province.ID,
        Denominazione = comuni.Province.Denominazione,
        Sigla = comuni.Province.Sigla
    }
}

using 7.12.2 all working OK!

habbes commented 1 year ago

Hi @premiaware this seems to be a regression caused by changes made in #2506, we fixed a similar issue in #2535. Should be fairly easy to fix. I'm interest in knowing the exact conditions that cause this failure and how I can reproduce it.

Could you tell me about the model? Is Comuni an entity set? is ComuneProvinciaBridge an entity type defined in the model? Same with the other classes in the sample code?

Could you share the schema definitions of the following types:

If possible, could you also try to find the minimal sample it takes for the problem to occur, for example, if you remove certain property assignments from the code, does the exception still occur? For example, does the following cause an error:

from comuni in Comuni
where comuni.ID == ID
select new ComuneProvinciaBridge
{
    Comune = new ComuniBridge
    {
        ID = comuni.ID
    }
}
habbes commented 1 year ago

Managed to reproduce the issue, it seems to occur under the following conditions:

This is what causes the ProjectPlanCompiler.GetDeepestEntry() method to eventually get called, as it tries to keep track of how it gets to this nested path from the source.

premiaware commented 1 year ago

Hi, thank's for support.

comuni is a entity on db

DataBridge is my class


    public class ComuneProvinciaBridge : DataBridge
    {
        public override void PrimaryKeyChange(long IDvalue) { }

        public ComuneProvinciaBridge()
        {
            _Comune = new ComuniBridge();
            _Provincia = new ProvinceBridge();
        }

        public ComuniBridge _Comune = null;
        public ProvinceBridge _Provincia = null;

        [JsonProperty("Comune")]
        public ComuniBridge Comune
                {
                get { return _Comune; }
                set { _Comune = value;}
                }

        [JsonProperty("Provincia")]
        public ProvinceBridge Provincia
                {
                get { return _Provincia; }
                set { _Provincia = value; }
                }

        public enum ComuneProvinciaState
        {
            empty,
            selected,
            unselected,
        };

        public async Task CaricaTuttiDettagli(IDataRepository dataRepository)
        {
            ComuneProvinciaBridge tmpComuni = await Task<ComuneProvinciaBridge>.Run(() => { return dataRepository.TrovaComuneAsync(this.Comune.ID, true).Result; });
            if (tmpComuni != null)
                Comune = tmpComuni.Comune;
        }

        public ComuneProvinciaState Status { get; set; } = ComuneProvinciaState.empty;
    };

  public class ComuniBridge : DataBridge
    {
        public override void PrimaryKeyChange(long IDvalue) { ID = IDvalue; }

        public ComuniBridge()
        {
        }

        private long _ID;
        [JsonProperty("ID")]
        public long ID
        {
            get { return _ID; }
            set
            {
                SetProperty(ref _ID, value);
            }
        }

        private long _ID_Provincia;
        [JsonProperty("ID_Provincia")]
        public long ID_Provincia
        {
            get { return _ID_Provincia; }
            set
            {
                SetProperty(ref _ID_Provincia, value);
            }
        }

        private long _ID_Agenzia;
        [JsonProperty("ID_Agenzia")]
        public long ID_Agenzia
        {
            get { return _ID_Agenzia; }
            set
            {
                SetProperty(ref _ID_Agenzia, value);
            }
        }

        private string _CodiceIstat;
        [JsonProperty("CodiceIstat")]
        public string CodiceIstat
        {
            get { return _CodiceIstat; }
            set
            {
                SetProperty(ref _CodiceIstat, value);
            }
        }

        private string _AliasCodiceIstat;
        [JsonProperty("AliasCodiceIstat")]
        public string AliasCodiceIstat
        {
            get { return _AliasCodiceIstat; }
            set
            {
                SetProperty(ref _AliasCodiceIstat, value);
            }
        }

        private string _CodiceFiscale;
        [JsonProperty("CodiceFiscale")]
        public string CodiceFiscale
        {
            get { return _CodiceFiscale; }
            set
            {
                SetProperty(ref _CodiceFiscale, value);
            }
        }

        private string _CodiceCatastale;
        [JsonProperty("CodiceCatastale")]
        public string CodiceCatastale
        {
            get { return _CodiceCatastale; }
            set
            {
                SetProperty(ref _CodiceCatastale, value);
            }
        }

        private string _Codice;
        [JsonProperty("Codice")]
        public string Codice
        {
            get { return _Codice; }
            set
            {
                SetProperty(ref _Codice, value);
            }
        }

        private string _Denominazione;
        [JsonProperty("Denominazione")]
        public string Denominazione
        {
            get { return _Denominazione; }
            set
            {
                SetProperty(ref _Denominazione, value);
            }
        }

        private string _PrefissoTelefonico;
        [JsonProperty("PrefissoTelefonico")]
        public string PrefissoTelefonico
        {
            get { return _PrefissoTelefonico; }
            set
            {
                SetProperty(ref _PrefissoTelefonico, value);
            }
        }

        private GeographyPointData _PosizioneGPS = new GeographyPointData();
        //[JsonConverter(typeof(DbGeometryConverter))]
        [JsonProperty("PosizioneGPS")]
        public GeographyPointData PosizioneGPS
        {
            get { return _PosizioneGPS; }
            set
            {
                SetProperty(ref _PosizioneGPS, value);
            }
        }

    }

    public class ProvinceBridge : DataBridge
    {
        public override void PrimaryKeyChange(long IDvalue) { ID = IDvalue; }

        public ProvinceBridge()
        {
        }

        private long _ID;
        [JsonProperty("ID")]
        public long ID
        {
            get { return _ID; }
            set
            {
                SetProperty(ref _ID, value);
            }
        }

        private long _ID_Regione;
        [JsonProperty("ID_Regione")]
        public long ID_Regione
        {
            get { return _ID_Regione; }
            set
            {
                SetProperty(ref _ID_Regione, value);
            }
        }

        private long _ID_Agenzia;
        [JsonProperty("ID_Agenzia")]
        public long ID_Agenzia
        {
            get { return _ID_Agenzia; }
            set
            {
                SetProperty(ref _ID_Agenzia, value);
            }
        }

        private string _Denominazione;
        [JsonProperty("Denominazione")]
        public string Denominazione
        {
            get { return _Denominazione; }
            set
            {
                SetProperty(ref _Denominazione, value);
            }
        }

        private string _Sigla;
        [JsonProperty("Sigla")]
        public string Sigla
        {
            get { return _Sigla; }
            set
            {
                SetProperty(ref _Sigla, value);
            }
        }
    }
habbes commented 1 year ago

Thanks @premiaware I've created a PR that should fix the issue: https://github.com/OData/odata.net/pull/2624

habbes commented 1 year ago

@premiaware just to confirm, is comuni.Provincia a navigation property or a complex property? In other words, does the Provincia property link to another entity?

premiaware commented 1 year ago
from comuni in Comuni      --> Comuni is Entity DB
where comuni.ID == ID
select new ComuneProvinciaBridge   --> ComuneProvinciaBridge  is my Object Class
{
    Comune = new ComuniBridge --> ComuniBridge is my Object Class
    {
        ID = comuni.ID,      --> Primary Key of entity
        Denominazione = comuni.Denominazione   --> Member of entity
    },
    Provincia = new ProvinceBridge --> ProvinceBridge is my Object Class
    {
        ID = comuni.Province.ID,   --> Primary Key of entity Provincie and Province is Property Navigation of Comuni
        Denominazione = comuni.Province.Denominazione, --> Member of entity Provincie and Province is Property Navigation of Comuni
        Sigla = comuni.Province.Sigla -> Member of entity Provincie and Province is Property Navigation of 
    }
}

I hope I understand what you are asking

could this problem issue be related to this other problem?

https://github.com/OData/AspNetCoreOData/issues/760