Home > Mobile >  C# Object doesnt support FirstOrDefault() depending on the input parameter
C# Object doesnt support FirstOrDefault() depending on the input parameter

Time:12-19

I don't know why the return value of the LoadData function (shown below) in one case supports the FirstOrDefault() method and in another case doesn't. In both cases it is the same return type.

The only difference is the way in which the dynamic parameter is created.

    public async Task<LookupModel?> UpdateLookup(LookupModel item, Guid newUk)
        var p1 = new
        {
            item.Code,
            item.Name,
            item.uk,
            newUk
        };

        var result1 = await _db.LoadData<LookupModel, dynamic>("lu.Lookup_Update", p1);
                // result1.GetType() = System.Collections.Generic.List`1[DataAccess.Models.Lookups.LookupModel]
        var rtv1 = result1.FirstOrDefault();        // ok


        var p2 = item.GetUpdateParams(newUk);
        
        var result2 = await _db.LoadData<LookupModel, dynamic>("lu.Lookup_Update", p2);
                // result2.GetType() = System.Collections.Generic.List`1[DataAccess.Models.Lookups.LookupModel]

        var rtv2 = result2.FirstOrDefault();        // not ok
                                                    // This throws an exception as FirstOrDefault() is not defined

        return rtv1;
    }

    // LookupModel
    public dynamic GetUpdateParams(Guid newUk)
    {
        return new
        {
            this.Code,
            this.Name,
            this.uk,
            newUK
        };
    }

    // LoadData
    public async Task<IEnumerable<T>> LoadData<T, U>(string storedProcedure, U parameters, string connectionId = "Default")
    {
        using IDbConnection connection = new SqlConnection(_config.GetConnectionString(connectionId));
        return await connection.QueryAsync<T>(storedProcedure, parameters, commandType: CommandType.StoredProcedure);

    }


CodePudding user response:

try this

return (await connection
.QueryAsync<T>(storedProcedure, parameters, commandType: CommandType.StoredProcedure))
.ToList();

CodePudding user response:

Because p1 is of a concrete type, whereas p2 is of type object (at runtime). So at run time, LoadData will be generic over the anonymous type or object respectively. Since object does not have any properties, that fails.

I suggest that to fix this you clone p2 to a concrete anonymous type before calling LoadData

var p2clone = new { foo = p2.foo ...};
var bar = LoadData(p2clone)

CodePudding user response:

p2 is dynamic, which means that result2 is also dynamic, and FirstOrDefault is an extension. Since the object type is not known at compile time, you can't call an extension method on it.

You can still do this by using the actual static method instead of an extension method:

var rtv2 = Enumerable.FirstOrDefault(result2);

since the static method can be bound at run-time.

But I would just change GetUpdateParams so that it returns a named type rather than an anonymous type, and then you don't have to use dynamic. That will also get you more type safety since the compiler can do type checking and you don't have to wait until runtime to find type errors.

  • Related