#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.