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

标签 c# entity-framework collections

我按照 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 中归档用户收藏。

关于c# - 搜索单个结果时与 Entity Framework 一起使用的集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16722636/

相关文章:

c# - C# 中的后期评估?

c# - Entity Framework - 只更新不为空的值

c# - 表为空时句柄 MAX() 的正确选项?

java - 为什么要使用 Deque 而不是内置 Stack<>?

c# - 在类里面获取路线数据

c# - 如何在C#中获取MonthCalendar控件的选定日期

c# - 加载相关对象时出现异常。 Entity Framework

.net - 伪造 Entity Framework 4.1 的 DbContext 进行测试

声明时的 Java 集合初始化与空检查

java - 如何过滤 Java 集合(基于谓词)?