Поиск в базе данных свойств (количество) с Entity Framework

#entity-framework

#entity-framework

Вопрос:

У меня есть немного неясная модель, в которой пользователи приходят из Active Directory, но с этого момента информация поступает из базы данных SQL.

Итак, у меня есть UserRepository, который в настоящее время позволяет пользователям выполнять поиск других пользователей из active Directory — это возвращает список, который я привязываю к сетке.

Мне нужно иметь возможность проверять, есть ли у каждого пользователя какие-либо контакты (которые живут в БД), чтобы изменить поведение пользовательского интерфейса.

Как бы вы это сделали? На другой странице контакты будут доступны для редактирования, но в списке мне просто нужно знать, есть ли какие-либо контакты или нет. Я не вижу никакого чистого способа обойти затраты на вызов базы данных для выполнения хранимой процедуры для каждого результата, чтобы получить количество, и я получаю количество, а не список контактов, чтобы сохранить его как можно более упорядоченным.

Я думал о чем-то в строках:

 /// <summary>
/// information resides in the database
/// </summary>
private int? contactsCount = null;
public int ContactsCount
{
  get
  {
    if (!contactsCount.HasValue)
      throw new ApplicationException("Error trying to access property ContactsCount before it has been initialised. The underlying repository code needs to handle the retrieval of this info.");
    return contactsCount.Value;
  }
  set { contactsCount = value; }
}
  

и использование UserRepository для установки значения ContactsCount после поиска по каждой строке (с использованием стандартного подключения sql), но было бы неплохо увидеть Entity Framework в действии на фактическом свойстве, но я не уверен, что смогу привязать только свойство к функции, если основной пользовательский объект не является частью Entity Model?

Ответ №1:

Это невозможно напрямую с Entity Framework. Я думаю, что это идеально подходит для выделенного класса UserRepository, который у вас уже есть.

В качестве дополнительного примечания я бы постарался избежать отдельного вызова базы данных для каждого пользователя, вместо этого вы можете решить это с помощью одного запроса, что-то вроде этого [предупреждение: впереди непроверенный код]:

  var users = GetUsersFromActiveDirectory();


 // get the nof contacts per user fill in the contacts count for each user
 // assuming a IsContactFrom property on Contact here, which corresponds to User.UserName
 // also, assuming the number of users this is called for is 'reasonable' 
 using (db = new MyObjectContext())
 {
     var userNames = users.Select(u => u.UserName).ToList(); 

     var usersWithContacts = from c in db.Contacts
                             where userNames.Contains(c.IsContactFrom)
                             group by c.IsContactFrom into ContactsPerUser
                             select new 
                             {
                                UserName = c.IsContactFrom, 
                                NofContacts = ContactsPerUser.Count()
                             };

     var dic = usersWithContacts.ToDictionary(u => u.UserName);

     foreach (var u in users)
     {
         u.ContactsCount = usersWithContacts[u.UserName].Count
     }




 }
  

Ответ №2:

Я не совсем уверен, что вам нужно. Если у вас есть таблица контактов со столбцом, который называется Login, тогда вы можете выполнить что-то в этом роде

 var qry = from c in ctx.Contacts
    group c by c.Login
    into grp
    select new
    {
      Login = grp.Key,
      Count = grp.Count()
    };
  

Предполагая, что у вас есть IEnumerable<User> users , который хранит список пользователей из active Directory, вы можете сделать это для объединения результатов:

 var dictionary = qry.ToDictionary(x => x.Login);
users.Foreach( x=> x.ContactsCount = dictionary.ContainsKey(x.Login) ? dictionary[x.Login].Count : 0);
  

Это предполагает, что у вас есть свойство ContactsCount, определенное в вашем классе User, где Foreach определяется следующим образом (метод расширения, который я использую довольно часто):

 public static void Foreach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
    foreach (T value in enumerable)
    {
        action(value);
    }
}