Более эффективный метод для запроса дважды разделенных или более объектов в цепочке отношений? - PullRequest
0 голосов
/ 20 апреля 2010

Не уверен, что я использую правильный термин, но это не дочерний / родительский элемент, поскольку они не являются вложенными объектами. В моем приложении у меня есть объекты User, UserUserGroup и UserGroup, которые довольно стандартны, UserUserGroup является связующим объектом с соответствующими идентификаторами. Я использую Linq-to-SQL, поэтому, к сожалению, он не использовал вложенные объекты, но все равно знает отношение.

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

    Public Class UserDao
    Inherits EntityDao(Of User)

    Public Function getListOfUsersByUserGroupName(ByVal userGroupName As String) As IList(Of User)

        Dim userList As New List(Of User)

        If Not userGroupName Is Nothing Then
            Dim userGroupDao As New UserGroupDao()
            Dim userUserGroupDao As New UserUserGroupDao()

            Dim userGroup As New UserGroup()
            userGroup = userGroupDao.getOneByValueOfProperty("Name", userGroupName)

            If Not userGroup Is Nothing Then

                Dim userUserGroup As IQueryable(Of UserUserGroup) = userUserGroupDao.getListByValueOfProperty("UserGroupId", userGroup.Id)

                If Not userUserGroup Is Nothing Then
                    Dim userDao As New UserDao()
                    Dim user As New User()

                    For Each entry As UserUserGroup In userUserGroup
                        Dim result As UserUserGroup = entry
                        user = userDao.getOneByValueOfProperty("Id", result.Id)
                        userList.Add(user)
                    Next

                End If
            End If

        End If

        Return userList

    End Function

End Class

Есть ли способ сделать это лучше с меньшим количеством линий и более эффективным? Мне кажется невероятно неэффективным сначала получить идентификатор предоставленной группы пользователей, затем получить результаты в UserUserGroup, где UserGroupId равен этому, затем получить все идентификаторы пользователей из этого запроса, а затем для каждого из этих идентификаторов запросить таблицу User, чтобы получить объект, соответствующий этому идентификатору. Это просто плохо для одного «результата». Я выполняю как минимум 3 запроса, каждый из которых создает и удаляет dataContexts. Кажется, что это обойдется налогом, особенно для каждого цикла, если будет возвращено множество результатов.

1 Ответ

1 голос
/ 20 апреля 2010

Я думаю, что вы можете сделать относительно легко в LINQ to SQL, но структура вашего уровня данных неожиданна с точки зрения LINQ. Я ожидаю, что если вы используете конструктор и у вас есть отношения, определенные в базе данных, у вас будут наборы сущностей, и вы сможете их использовать. Более естественный способ использования контекста данных, скажем, шаблона Repository, в качестве основы для запроса, вероятно, будет работать лучше. По сути, вам нужны пользователи, у которых есть какие-либо ассоциации, в которых набор групп, с которыми они связаны, содержит группу с соответствующим именем.

РЕДАКТИРОВАТЬ : Я думаю, что я на самом деле говорю пусть LINQ будет LINQ . LINQ - это ориентированный на контекст данных ORM (облегченный), и вам нужно подумать об использовании LINQ с точки зрения контекста данных, чтобы он действительно работал для вас. Если вы будете придерживаться своей предыдущей перспективы, ориентированной на объекты данных, я думаю, вы будете разочарованы в LINQ.

Пример (в C #) - это не полный пример того, как реализовать репозиторий, просто в иллюстративных целях.

public class UserRepository : IDisposable
{
   private DataContext Context { get; set; }
   private bool DisposeContext { get; set; }

   public UserRepository() : this( null ) { }

   public UserRepository( DataContext context ) // manual constructor injection
   {
      this.Context = context ?? new MyDataContext();
      this.DisposeContext = context == null;
   }

   public IQueryable<User> GetListOfUsersByUserGroupName( string userGroupName )
   {     
      return Context.Users
                    .Where( u => u.UserUserGroups
                                  .Any( uug => uug.Groups
                                                  .Any( ug => ug.GroupName == userGroupName ) );
   }

   ...

   public void SaveChanges()
   {
        Context.SubmitChanges();
   }

   // insert canonical IDisposable pattern here and dispose of
   // the data context if needed, don't dispose if injected
}

Используется как:

 using (var repository = new UserRepository())
 {
     var users = repository.GetListOfUsersByUserGroupName( "admin" );
     foreach (var admin in users)
     {
         SendMessage( admin, notification );
         admin.LastNotified = DateTime.Now;
     }
     repository.SaveChanges();
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...