【问题标题】:How to use data from entity Raw SQL query in entity framework如何在实体框架中使用实体原始 SQL 查询中的数据
【发布时间】:2021-01-08 19:49:36
【问题描述】:

我先声明一下,我对 asp.net 核心和实体框架仍然很陌生,但我熟悉 ADO 和记录集,它似乎是构建实体框架的基础。我正在努力使用实体框架,因为我能够运行查询,但我不确定如何使用结果,我在网上看到的大多数帮助文档只讨论了程序和方法,而不是如何使用结果。我正在我的网站上构建登录功能,并开发了以下代码来查询我的 UserAccount 表中的数据库。对于这个登录,我真的只想要用户名、密码和 ID,但是我在这个表中有多个字段,这方面我不需要。我来自使用 ADO 和记录集,所以实际上我只是更喜欢使用原始 sql 并确定我想对这些结果做什么,而不是将它们绑定到实体框架在大多数情况下所做的某些对象。我确实喜欢实体框架的易用性和使用参数,所以我更喜欢走这条路(不确定这是否是不好的做法)。一切都很好,除了当我添加 ToList 时它开始说错误“InvalidOperationException:所需的列‘AccessLevel’不在‘FromSql’操作的结果中。”我什至没有尝试在查询中使用该字段,所以不确定为什么会出现这种情况,我使用的是 rawsql 查询方法,那么为什么它试图查看我在该表的模型中拥有什么?最后,这应该返回一条记录,在这种情况下,我想从该记录字段中提取密码值,类似于我在 ADO 中使用的方式,正如您将在我的密码哈希验证中看到的那样,但我无法弄清楚如何从该记录字段中提取密码值查询结果。感谢您对此的任何帮助,因为我在尝试学习这些东西时感到头疼!

               var UserResults = _context.UserAccounts.FromSqlInterpolated($"SELECT USERACCOUNT.USERNAME, USERACCOUNT.PASSWORD, USERACCOUNT.ID,USERACCOUNT.ACCESS_LEVEL FROM DBO.USERACCOUNT WHERE USERACCOUNT.USERNAME={UserName}");

            if (UserResults.Count() == 1) //if we have more than 1 result we have security issue so do not allow login
            {
                var passwordHasher = new PasswordHasher<string>();
                var hashedPassword = passwordHasher.HashPassword(null, Password);

                var testResults = UserResults.ToList();

                if (passwordHasher.VerifyHashedPassword(null, hashedPassword, THIS SHOULD BE VALUE FROM DB RIGHT HERE!!!) == PasswordVerificationResult.Success)
                {
                    var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, UserName)
                };

我的DBContext如下:

public partial class LoginDBContext : DbContext
{
    public DbSet<UserAccount> UserAccounts { get; set; }

    public LoginDBContext(DbContextOptions<LoginDBContext> options) : base(options)
    {

    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserAccount>(entity =>
        {
            //entity.ToTable("UserAccount");
            entity.HasNoKey();

            //entity.Property(e => e.Id)
            //    .HasMaxLength(50)
            //    .IsUnicode(false);

            //entity.Property(e => e.Username)
            //    .HasMaxLength(50)
            //    .IsUnicode(false);
            //entity.Property(e => e.Password)
            //    .HasMaxLength(50)
            //    .IsUnicode(false);
        });
    }
}

【问题讨论】:

    标签: entity-framework asp.net-core


    【解决方案1】:

    如果您不想加载用户表的所有列,您可以返回具有您需要的属性的匿名对象,或者为您需要的列创建一个类并返回它。

    var users = _context.UserAccounts
        .Where(a => a.UserName == UserName)
        .Select(a => new { a.Id, a.UserName, a.Password })
        .ToArray();
    
    if (users.Length == 1)
    {
        var user = users.First();
        if (passwordHasher.VerifyHashedPassword(null, hashedPassword, user.Password) == PasswordVerificationResult.Success)
        {
            // ... your magic
        }
    }
    

    【讨论】:

    • 所以你甚至没有使用 fromsqlinterpolated()?有没有办法用我的代码等原始 sql 来做到这一点?
    • FromRowSql 期望返回一个实体,因此它要求提供所有列。你说我正在努力使用实体框架 - 你这样做是因为你没有按照它的设计用途使用它。 FromRawSql 的使用仅适用于“例外”情况。如果您不打算使用静态类型查询,那么您的斗争将继续 - 寻找其他一些 ORM 框架;)
    • 你说得对,我可能应该强迫自己继续使用它来学习它。我将根据您的内容调整我的代码,但要进一步了解为什么 UserAccount 甚至可以工作,我是否需要根据上面的内容调整我的 DBContext 文件。我注释掉了 ToTable("UserAccount") 但我假设我应该使用它来创建链接以便它知道表格?此外,您通常是否在同一个文件中为每个表创建一个 DBContext(即 modelBuilder.Entity 为一个文件中的每个表)。
    • EF默认使用实体类型名作为表名,表名和类型名不同时使用ToTable('name")。您可以在一个文件中配置一个 DbContext 中的多个表。
    • 啊,明白了。我想在这种情况下,ModelBuilder 对我来说真的不是必需的,因为它完全一样。只是好奇你对此的看法。如果我非常熟悉 SQL 并且在 VBA 项目中经常使用 ADO,您认为我会更适合使用 ADO.NET 来让应用程序与数据库进行通信,还是您认为实体框架可能更好强制执行从零开始学习?
    猜你喜欢
    • 1970-01-01
    • 2015-06-16
    • 2015-04-25
    • 2013-03-08
    • 2021-03-02
    • 2021-04-26
    • 2016-05-20
    • 1970-01-01
    • 2011-12-29
    相关资源
    最近更新 更多