Raw SQL Query without DbSet - Entity Framework Core

后端 未结 17 1194
眼角桃花
眼角桃花 2020-11-22 13:27

With Entity Framework Core removing dbData.Database.SqlQuery I can\'t find a solution to build a raw SQL Query for my full-text search query th

相关标签:
17条回答
  • 2020-11-22 13:53

    You can use this (from https://github.com/aspnet/EntityFrameworkCore/issues/1862#issuecomment-451671168 ) :

    public static class SqlQueryExtensions
    {
        public static IList<T> SqlQuery<T>(this DbContext db, string sql, params object[] parameters) where T : class
        {
            using (var db2 = new ContextForQueryType<T>(db.Database.GetDbConnection()))
            {
                return db2.Query<T>().FromSql(sql, parameters).ToList();
            }
        }
    
        private class ContextForQueryType<T> : DbContext where T : class
        {
            private readonly DbConnection connection;
    
            public ContextForQueryType(DbConnection connection)
            {
                this.connection = connection;
            }
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                // switch on the connection type name to enable support multiple providers
                // var name = con.GetType().Name;
                optionsBuilder.UseSqlServer(connection, options => options.EnableRetryOnFailure());
    
                base.OnConfiguring(optionsBuilder);
            }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.Entity<T>().HasNoKey();
                base.OnModelCreating(modelBuilder);
            }
        }
    }
    

    And the usage:

        using (var db = new Db())
        {
            var results = db.SqlQuery<ArbitraryType>("select 1 id, 'joe' name");
            //or with an anonymous type like this
            var results2 = db.SqlQuery(() => new { id =1, name=""},"select 1 id, 'joe' name");
        }
    
    0 讨论(0)
  • 2020-11-22 13:54

    I used Dapper to bypass this constraint of Entity framework Core.

    IDbConnection.Query
    

    is working with either sql query or stored procedure with multiple parameters. By the way it's a bit faster (see benchmark tests )

    Dapper is easy to learn. It took 15 minutes to write and run stored procedure with parameters. Anyway you may use both EF and Dapper. Below is an example:

     public class PodborsByParametersService
    {
        string _connectionString = null;
    
    
        public PodborsByParametersService(string connStr)
        {
            this._connectionString = connStr;
    
        }
    
        public IList<TyreSearchResult> GetTyres(TyresPodborView pb,bool isPartner,string partnerId ,int pointId)
        {
    
            string sqltext  "spGetTyresPartnerToClient";
    
            var p = new DynamicParameters();
            p.Add("@PartnerID", partnerId);
            p.Add("@PartnerPointID", pointId);
    
            using (IDbConnection db = new SqlConnection(_connectionString))
            {
                return db.Query<TyreSearchResult>(sqltext, p,null,true,null,CommandType.StoredProcedure).ToList();
            }
    
    
            }
    }
    
    0 讨论(0)
  • 2020-11-22 13:54

    You can also use QueryFirst. Like Dapper, this is totally outside EF. Unlike Dapper (or EF), you don't need to maintain the POCO, you edit your sql SQL in a real environment, and it's continually revalidated against the DB. Disclaimer: I'm the author of QueryFirst.

    0 讨论(0)
  • 2020-11-22 13:55

    My case used stored procedure instead of raw SQL

    Created a class

    Public class School
    {
        [Key]
        public Guid SchoolId { get; set; }
        public string Name { get; set; }
        public string Branch { get; set; }
        public int NumberOfStudents  { get; set; }
    }
    

    Added below on my DbContext class

    public DbSet<School> SP_Schools { get; set; }
    

    To execute the stored procedure:

    var MySchools = _db.SP_Schools.FromSqlRaw("GetSchools @schoolId, @page, @size ",
                  new SqlParameter("schoolId", schoolId),
                  new SqlParameter("page", page),
                  new SqlParameter("size", size)))
    .IgnoreQueryFilters();
    
    0 讨论(0)
  • 2020-11-22 13:57

    For now, until there is something new from EFCore I would used a command and map it manually

      using (var command = this.DbContext.Database.GetDbConnection().CreateCommand())
      {
          command.CommandText = "SELECT ... WHERE ...> @p1)";
          command.CommandType = CommandType.Text;
          var parameter = new SqlParameter("@p1",...);
          command.Parameters.Add(parameter);
    
          this.DbContext.Database.OpenConnection();
    
          using (var result = command.ExecuteReader())
          {
             while (result.Read())
             {
                .... // Map to your entity
             }
          }
      }
    

    Try to SqlParameter to avoid Sql Injection.

     dbData.Product.FromSql("SQL SCRIPT");
    

    FromSql doesn't work with full query. Example if you want to include a WHERE clause it will be ignored.

    Some Links:

    Executing Raw SQL Queries using Entity Framework Core

    Raw SQL Queries

    0 讨论(0)
提交回复
热议问题