Получение ошибки о том, что «‘object’ не содержит определения для ‘key'» при доступе к свойству ключа в Asp.Net

#asp.net #linq #group-by

#asp.net #linq #групповое

Вопрос:

Я много исследовал, но я не могу понять, почему я получаю эту ошибку, во время отладки я вижу значение ключа в «fgroup», но все равно он выдает ошибку ниже:-

 {
    "Message": "An error has occurred.",

    "ExceptionMessage": "'object' does not contain a definition for 'key'",

    "ExceptionType": "Microsoft.CSharp.RuntimeBinder.RuntimeBinderException",

    "StackTrace": "   at CallSite.Target(Closure , CallSite , Object )rn   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)rn   at WEBAPINILAYAM.Controllers.HomeController.TempMethod(List`1 firstRecord, List`1 secoudRecord)rn   at WEBAPINILAYAM.Controllers.HomeController.<GetUserList>d__1.MoveNext()rn--- End of stack trace from previous location where exception was thrown ---rn   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__1`1.MoveNext()rn--- End of stack trace from previous location where exception was thrown ---rn   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()rn--- End of stack trace from previous location where exception was thrown ---rn   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()rn--- End of stack trace from previous location where exception was thrown ---rn   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()rn--- End of stack trace from previous location where exception was thrown ---rn   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()"

}

 

Пожалуйста, найдите мой код ниже:-

  var flatuser = await (from f in DatabaseContext.FlatUserDetails
                                  where f.SocietyCode.Equals(SocietyCode)                                   
                                  select new
                                  { 
                                      userName = f.Users.UserName,
                                      fullName = f.Users.FullName,
                                      phoneNumber = f.Users.PhoneNumber,
                                      email = f.Users.Email,                       
                                      flatNumber = f.FlatDetails.FlatNumber,
                                      buildingNumber = f.BuildingDetails.BuildingNumber

                                  }).GroupBy(x => x.userName).ToListAsync<dynamic>();

  foreach (var fgroup in flatuser)
    {
                                
                String k = fgroup.key;  // Getting error at this line

  foreach(var temp in fgroup)
           {
                 // accessing the object

            }

     }
 

Пожалуйста, помогите мне, я хочу получить значение ключа.

Комментарии:

1. Я пробовал «fgroup. Ключ» также, но все та же ошибка.

2. Используете ли вы foreach in View?

3. нет, это веб-API, я использую его внутри метода в контроллере.

4. Почему вы используете dynamic ?

5. Я использовал dynamic, потому что я не использую объект класса модели, все переменные внутри select имеют анонимный тип. Если я удалю dynamic, мне нужно сначала создать класс модели и создать его объект в запросе с определенным свойством.

Ответ №1:

Причиной вашей ошибки является использование вашего .ToListAsync<dynamic>();

Решение состоит в том, чтобы завершить ваш запрос с .ToListAsync();

… все переменные внутри select имеют анонимный тип. Если я удалю dynamic, мне нужно сначала создать класс модели и создать его объект в запросе с определенным свойством

Это верно только в том случае, если вы хотите вернуть извлеченные данные из метода. Если вы хотите поместить их только в анонимный тип и использовать сразу после него, как вы делали в своем коде, тогда вы можете использовать свой анонимный тип.

Давайте сделаем это на простом примере. Давайте создадим клиента, последовательность клиентов и GroupbBy.

Просто сделайте это в простой консольной программе:

 class Program
{
    static void Main(string[] args)
    {
        var flatUsers = new []
        {
            new {Id=1, UserName="A", FullName="A B"},
            new {Id=2, UserName="B", FullName="B C"},
            new {Id=3, UserName="C", FullName="D E"},
            new {Id=4, UserName="A", FullName="A E"},
            new {Id=5, UserName="C", FullName="C D"},
            new {Id=6, UserName="D", FullName="D E"},
            new {Id=7, UserName="A", FullName="A D"},
            new {Id=8, UserName="B", FullName="D F"},
       };
 

В Visual Studio, если вы наведете курсор мыши на переменную flatUsers , будет указано, что это массив некоторого анонимного типа.

Поэкспериментируйте с этим. Добавьте a ToList() и посмотрите, что произойдет, или добавьте a Select(flatUser => new {...} и посмотрите, каков результат.

Создайте группы плоских пользователей, которые имеют одинаковые UserName :

 var flatUsersGroupedByUserName = flatUsers.GroupBy(flatUser => flatUser.UserName);
 

Еще раз: наведите курсор мыши. Это говорит о том, что переменная является `IEnumerable<IGrouping<string, некоторый анонимный тип>>

Теперь мы можем использовать этот анонимный тип? Давайте попробуем:

 foreach (var flatUserGroup in flatUsersGroupedByUserName)
{
    Console.WriteLine("Flat users in group "   flatUserGroup.Key.ToString()
    foreach (flatUser in flatUserGroup)
    {
         Console.WriteLine("[{0}] {1} - {2} ", flatUser.Id, flatUser.UserName, flatUser.FullName);
    }
}
 

Итак, если вы создаете анонимный тип, вы можете использовать его до тех пор, пока вы используете тот же метод.

Вы не можете вернуть анонимный тип метода: ему нужен возвращаемый тип.

 <return type needed here> GetFlatUserGroups (...);
 

Конечно, вы могли бы использовать List<dynamic> here в качестве возвращаемого типа, но в этом случае пользователям вашего метода было бы очень сложно узнать, что находится в списке. Я не уверен, что это было бы разумно. Ошибки не будут обнаружены до времени выполнения. Если вы действительно не можете сообщить вызывающим ваш метод, что находится в возвращаемом значении, подумайте о том, чтобы вернуть List и позволить вашим вызывающим использовать отражение, чтобы узнать, что в нем. Но опять же: старайтесь избегать этого. Тот факт, что вы не хотите вводить класс для возвращаемого значения, не является веской причиной. Спросите своего руководителя проекта, и он согласится.

Резюмирую: пожалуйста, используйте анонимный тип. Поэкспериментируйте, чтобы познакомиться с ними. Анонимные типы имеют полную проверку типов. Вы обнаружите ошибки во время компиляции. Старайтесь избегать использования dynamic.