Разъяснение взаимодействия Linq, EntityQuery и RIA Services - PullRequest
1 голос
/ 15 марта 2012

У меня есть общий вопрос о взаимодействии linq с entityquery и ria services. Я знаю, что в моем domainconext я могу определять запросы для моего приложения. Например, я могу использовать linq внутри моего domaincontext для определения следующего запроса:

    public IQueryable<User> GetUsersFriends(Guid usersID)
    {
        return (from f in this.ObjectContext.Friends join u in this.ObjectContext.Users on f.FriendUsersID equals u.ID where f.UsersID.Equals(usersID) select u);
    }

Это все хорошо. Но мой вопрос, могу ли я выполнить тот же тип запроса со стороны клиента (приложение silverlight) ? Так можно ли создать оператор linq для объекта EntityQuery и таким образом вернуть данные из базы данных?

Я знаю, что могу выполнять операции linq над коллекциями сущностей, которые уже были загружены? Могу ли я использовать linq на стороне клиента для загрузки коллекций?

Я думаю, что все запросы, которые в конечном итоге попадают в базу данных, должны быть определены в контексте моего домена? В силу привычки я продолжаю пытаться использовать linq для определения новых запросов и передачи их в операцию domaincontext.load () .... которая с треском проваливается. Domainconext, вероятно, не имеет никакого способа маршалировать запросы через строку ... правильно?

Правильно ли мое понимание? Если бы кто-то мог помочь мне это проверить, я был бы признателен.

1 Ответ

2 голосов
/ 16 марта 2012

Одним из основных преимуществ IQueryable (и это также довольно хороший риск для безопасности) является то, что вы МОЖЕТЕ создать запрос на стороне клиента и сериализовать его обратно на сервер для обработки на сервере. Здесь необходимо, чтобы он возвращал определенный тип (в вашем случае IQueryable, где User - это тип, который должен возвращаться в коллекции, поддерживающей IEnumerable <>.

Я взял свой пример у Шона Вильдермута (wildermuth.com) и немного подправил его. Это то, что я использую в своей «модели» на стороне клиента.

publicvoid PerformQuery<T>(EntityQuery<T> qry, EventHandler<EntityResultsArgs<T>> evt, object pUserState = null, bool NoRecordsThrow = False, LoadBehavior pLoadBehavior = LoadBehavior.MergeIntoCurrent ) where T : Entity
{

  ModelDataContext.Load<T>(
    qry,
    pLoadBehavior,
    r =>
    {

      if (evt != null)
      {
        try
        {

          if (r.HasError)
          {

#if DEBUG

            System.Diagnostics.Debugger.Break();

#endif
            //internal class to record error messages
            AppMessages.ErrorMessage.Display(string.Concat(r.Error.Message, Environment.NewLine, "------------------------", "------- Stack Trace ------", Environment.NewLine, r.Error.StackTrace));
          }
          else if (r.Entities.Count() > 0 || NoRecordsThrow)
            evt(this, new EntityResultsArgs<T>(r.Entities, r.UserState));
        }
        catch (Exception ex)
        {
#if DEBUG
          System.Diagnostics.Debugger.Break();
#endif
          evt(this, new EntityResultsArgs<T>(ex));
        }
      }
    },
    pUserState);
}

Когда бы я тогда использовал это так:

var UserQuery =  <DomainServiceName>.Users.Where(pUser => pUsers.City == "Calgary");
PerformQuery<User>(UserQuery, UserQueryComplete)

Недостатком является то, что через эту одну конечную точку пользовательские данные могут быть извлечены с помощью любого вида фильтра, который выдается на стороне клиента ....

НТН, Ричард

...