2014-11-09 2 views
0

У меня есть 4 таблицы, UserCredential, UserProfile, UserRoles и RoleLinq многие ко многим отношения Регистрация

var user = (from uc in Db.UserCredentials 
       join up in Db.UserProfiles on uc.UserId equals up.UserId 
       join ur in Db.UserRoles on uc.UserId equals ur.UserId 
       select new { 
        Credetial = uc, 
        Profile = up, 
        Roles = Db.Roles.Where(r => r.RoleId == ur.RoleId)}) 
       .FirstOrDefault(); 

UserRole имеет UserId и RoleId, так что пользователь может иметь несколько ролей.

Запрос, генерируемый приведенным выше кодом, не представляется эффективным. Может ли кто-нибудь предложить лучший код

+0

EF автоматически создает свойства навигации для связи, поэтому вам не нужно использовать соединения. –

+0

Вы указываете EF и LINQ to SQL. Что вы используете? SQL, сгенерированный каждым, может быть совсем другим. Отправьте сгенерированный SQL и укажите, где вы считаете, что он неэффективен. Независимо от того, подумайте об этом как о графе объектов, а не о наборах с объединениями, и вы можете найти лучший вариант. –

ответ

0

Во-первых, поскольку мы обеспокоены производительностью, убедитесь, что ваша база данных имеет индексы для всех этих столбцов UserId и RoleId.

Поскольку у вас есть несколько UserRoles, в том числе в соединении, это расточительно увеличивает мощность вашего запроса, а затем вызывает вызов FirstOrDefault и возвращает его обратно. один? вы не показали, как вы выбираете конкретного пользователя, но я оставлю это до вас, чтобы исправить, если только он не фильтруется в одном из ваших источников данных.

Кроме того, свойство role на вашем анонимном объекте: каждый раз, когда вы его касаетесь, вы попадаете в базу данных. Это очень хорошо может быть источником проблем с производительностью. Если это приемлемо для кэширования этой информации, завершение подзапроса вызовом ToList() было бы разумным.

Этот подзапрос может стать еще одним источником неприятностей, особенно если вы используете ToList - это будет еще одна поездка в базу данных, поэтому убедитесь, что мощность основного запроса не установлена, чтобы контролировать количество поездок.

var user = (from uc in Db.UserCredentials 
      join up in Db.UserProfiles on uc.UserId equals up.UserId 
      //where uc.UserId == somePassedInUserId /* add this line if your datasources aren't filtered */ 
      select new { 
       Credetial = uc, 
       Profile = up, 
       Roles = (from ur in Db.UserRoles join r in Db.Roles on ur.RoleId equals r.RoleId 
          where ur.UserId == uc.UserId select r).ToList() 
      .FirstOrDefault(); 
Смежные вопросы