#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);
}
}