Skip to main content
 首页 » 编程设计

c#之搜索单个结果时与 Entity Framework 一起使用的集合

2024年02月13日31zhoujg

我按照 Entity Framework 教程编写了一个 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 还是其他什么?

请您参考如下方法:

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

我不明白你的架构 ApplicationConfig确切地说,但是你必须在某个地方调用:

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

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

编辑

如果ApplicationConfig类是模型和数据库中与 User 有关系的实体s 和 Role s 您仍然可以根据凭据和验证用户 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) 轻松包含用户的角色。在 context.Users 之后.

无论如何,关键是要有一个 context可一步执行完整验证。不要像加载 ApplicationConfig 那样把它分成两部分首先与所有用户一起,然后从加载的 Users 中归档用户收藏。