开发者

Property database lookup (count) with Entity Framework

I have a slightly obscure model in that Users come from Active Directory, but from then on in information arrives from the SQL db.

So, I have a UserRepository that currently allows users to search for other users from active directory - this returns a list that I bind to a grid.

I need to be able to check if each user has any Contacts (which live in the db) in order to change how the UI behaves.

How would you do this? On another page Contacts will be editable, but on the list I just need to know if there any Contacts or not. I dont see any clean way around the expense of issuing a db call to execute a stored procedure for each result to get the count, and I am getting the count rather than the list of Contacts to keep it as streamlined as possible.

I was thinking something on the lines:

/// <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; }
}开发者_运维知识库

and using the UserRepository to set the value of ContactsCount after the search for each row (using a standard sql connection), but what would be nice would be to see Entity Framework in action on the actual property but I am not sure I can bind just a property to a function if the main User object is not part of the Entity Model?


It's not possible directly with Entity Framework. I think this is a perfect fit for a dedicated UserRepository class, which you already have.

As a side note, I would try to avoid having a separate db call per user, instead you can solve this with a single query, something like this [warning: untested code ahead]:

 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
     }




 }


I'm not quite sure what you are after. If you have a Contact table with, a column that is called Login, then you can run something along these lines

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

Assuming that you have IEnumerable<User> users that keeps a list of users from active directory, you can then do this to merge the results:

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

This assumes that you have ContactsCount property defined on your User class, where Foreach is defined like this (an extension method that I find myself using quite often):

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜