1

我按照实体框架教程编写了一个 ApplicationConfig 模型(这是简化的) -

public class ApplicationConfig
{
    public ApplicationConfig()
    {
        this.Users = new Collection<User>();
        this.Roles = new Collection<Role>();
    }

    public string Namespace { get; set; }
    public virtual ICollection<User> Users { get; set; }
    public virtual ICollection<Role> Roles { get; set; }
}


public class User
{
    public User()
    {
        this.Roles = new Collection<Role>();
        this.ApplicationConfigs = new Collection<ApplicationConfig>();
    }

    public int UserId { get; set; }

    public string Username { get; set; }
    public string Password { get; set; }

    public virtual ICollection<Role> Roles { get; set; }
    public virtual ICollection<ApplicationConfig> ApplicationConfigs { get; set; }
}

我有一种方法可以检查特定应用程序的用户名/密码 -

public User ValidateUser(string applicationNamespace, string username, string password)
{
    var applicationConfig = GetApplicationConfig(applicationNamespace);

    User user = null;
    if (applicationConfig != null)
    {
       user = applicationConfig.Users.FirstOrDefault(u => u.Username.ToLower() == username && u.Password == password);
    }
    return user;
}

我可以有成百上千的应用程序用户,但对于这个密码检查,我只希望返回匹配的用户。

ICollection 和上面的查询是否可以用于此目的?

我主要担心的是applicationConfig.Users即使我只想查询一个用户,也会填满所有成千上万的用户。

或者我应该使用 IQueryable 或 IEnumerable 还是其他什么?

4

2 回答 2

4

看起来不太好。您的担忧是有效的,您必须使用IQueryable<User>最终返回到您的实体框架(或DbSet<User>)的(或),以确保您在加载数千个用户后实际在数据库中而不是在内存中查询用户。ObjectSet<User>DbContextObjectContext

我不完全了解您的架构ApplicationConfig,但是您必须在某个地方致电:

user = context.Users.FirstOrDefault(u =>
     u.Username.ToLower() == username && u.Password == password);

基本上相同的 LINQ 但使用(=您的派生(或) 的context实例) 而不是. 这将被翻译成在数据库中过滤用户的 SQL 查询。DbContextObjectContextapplicationConfig

编辑

如果该类是模型和数据库中与s 和sApplicationConfig有关系的实体,您仍然可以根据凭据单个数据库查询验证用户,而无需为应用程序加载所有用户。例如,它可能看起来像这样:UserRole applicationNamespace

public User ValidateUser(string applicationNamespace,
    string username, string password)
{
    return context.ApplicationConfigs
        .Where(a => a.Namespace == applicationNamespace)
        .Select(a => a.Users
            .Where(u => u.Username.ToLower() == username &&
                u.Password == password)
            .FirstOrDefault())
        .FirstOrDefault();
}

或者-如果您要为User实体提供一个ApplicationConfigs集合(根据您在下面的评论,我假设一个用户帐户可以参与许多应用程序-> 多对多关系)-您可以这样编写查询:

public User ValidateUser(string applicationNamespace,
    string username, string password)
{
    return context.Users
        .FirstOrDefault(u =>
            u.ApplicationConfigs.Any(a => a.Namespace == applicationNamespace) &&
            u.Username.ToLower() == username && u.Password == password);
}

我更喜欢后一个版本,因为如果需要,您可以通过添加Include(u => u.Roles)after轻松包含用户的角色context.Users

在任何情况下,关键是要有一个context可用于在一个步骤中执行完整验证的工具。不要将其分成两部分,例如将第ApplicationConfig一个与所有用户一起加载,然后从加载的Users集合中归档用户。

于 2013-05-23T20:15:13.100 回答
0

看起来不错。您可以简化退货:

public User ValidateUser(string applicationNamespace, string username, string password)
{
   var applicationConfig = GetApplicationConfig(applicationNamespace);

   if (applicationConfig != null)
   {
       return applicationConfig.Users.FirstOrDefault(u => u.Username.ToLower() == username && u.Password == password);
   }
   return null;
}
于 2013-05-23T19:54:56.890 回答