Entity Framework——使用SQL语句查询

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wlk1229/article/details/79947848

使用SQL语句查询

使用SQL语句查询比使用Linq更加灵活,查询效率也可以更高。EntityFramework支持直接使用SQL语句查询,使用DbContext.Database. SqlQuery< TElement >函数查询。该函数的文档介绍如下:

//     Creates a raw SQL query that will return elements of the given generic type.
//     The type can be any type that has properties that match the names of the columns
//     returned from the query, or can be a simple primitive type. The type does not
//     have to be an entity type. The results of this query are never tracked by the
//     context even if the type of object returned is an entity type. Use the System.Data.Entity.DbSet`1.SqlQuery(System.String,System.Object[])
//     method to return entities that are tracked by the context. As with any API that
//     accepts SQL it is important to parameterize any user input to protect against
//     a SQL injection attack. You can include parameter place holders in the SQL query
//     string and then supply parameter values as additional arguments. Any parameter
//     values you supply will automatically be converted to a DbParameter. context.Database.SqlQuery<Post>("SELECT
//     * FROM dbo.Posts WHERE Author = @p0", userSuppliedAuthor); Alternatively, you
//     can also construct a DbParameter and supply it to SqlQuery. This allows you to
//     use named parameters in the SQL query string. context.Database.SqlQuery<Post>("SELECT
//     * FROM dbo.Posts WHERE Author = @author", new SqlParameter("@author", userSuppliedAuthor));
//
// 参数:
//   sql:
//     The SQL query string.
//
//   parameters:
//     The parameters to apply to the SQL query string. If output parameters are used,
//     their values will not be available until the results have been read completely.
//     This is due to the underlying behavior of DbDataReader, see http://go.microsoft.com/fwlink/?LinkID=398589
//     for more details.
//
// 类型参数:
//   TElement:
//     The type of object returned by the query.
//
// 返回结果:
//     A System.Data.Entity.Infrastructure.DbRawSqlQuery`1 object that will execute
//     the query when it is enumerated.
public DbRawSqlQuery<TElement> SqlQuery<TElement>(string sql, params object[] parameters);

从介绍中我们可以知道,如果查询数据只有一列时,我可以直接使用int,string,DateTime等类型作为TElement类型查询,查询的结果会以一个list返回。

 如果查询有多列,查询结果会返回一个TElement类型的list,每一列数据会与TElement中的一个属性对应,对应的方式为,列名与属性名相同。如以下查询结果会与相应的类对应:

 

为了使用使用SQL语句进行查询,可以先为查询创建相应的类,然后查询。这种方法比较麻烦,因为我们可能只是想简单的查询几个数据,但查询还要我们先创建相应的类才行。为了减少类的创建,我们可以使用匿名类,但匿名类类型创建就比较麻烦,而且匿名类要使用反射机制,效率也不高。

 

为了更好的使用SQL语句查询,可以先用模板创建几个查了类,每次查询直接套用模板就行,这样即可省去创建类,查询效率也很高。查询类如下:

    public class Query2<T1, T2>
    {
        public T1 Q1 { get; set; }

        public T2 Q2 { get; set; }

        public Query2()
        {
        }
    }

    public class Query3<T1, T2, T3>
    {
        public T1 Q1 { get; set; }

        public T2 Q2 { get; set; }

        public T3 Q3 { get; set; }

        public Query3()
        {
        }
    }

    public class Query4<T1, T2, T3, T4>
    {
        public T1 Q1 { get; set; }

        public T2 Q2 { get; set; }

        public T3 Q3 { get; set; }

        public T4 Q4 { get; set; }

        public Query4()
        {
        }
    }

    public class Query5<T1, T2, T3, T4, T5>
    {
        public T1 Q1 { get; set; }

        public T2 Q2 { get; set; }

        public T3 Q3 { get; set; }

        public T4 Q4 { get; set; }

        public T5 Q5 { get; set; }

        public Query5()
        {
        }
    }

每个类对应查询需要的列数,这里我只创建了4个,实际项目中我们可以先多创建好几个,用的时候直接用就行。

使用查询类的例子如下:

    class Program
    {
        class TableItem
        {
            public int ID { get; set; }
            public string S1 { get; set; }
            public int I1 { get; set; }
            public DateTime D1 { get; set; }
        }

        class MyContex : DbContext
        {
            public const string connectstr = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=EFQuery;Integrated Security=True;";

            public DbSet<TableItem> TableItems { get; set; }

            public MyContex() :
                base(connectstr)
            {   }
        }

        static void Main(string[] args)
        {
            using (var db = new MyContex())
            {

                //db.TableItems.Add(new TableItem() { S1="a", I1= 1, D1 = new DateTime(2018, 04, 01) });
                //db.TableItems.Add(new TableItem() { S1 = "a", I1 = 2, D1 = new DateTime(2018, 04, 02) });
                //db.SaveChanges();

                var sql = "select S1 As Q1, COUNT(I1) As Q2, sum(I1) As Q3 from TableItems group by S1";
                var query = db.Database.SqlQuery<Query3<string, int, int>>(sql);
                Console.WriteLine($"Query SQL: {query.ToString()}");

                foreach (var item in query.ToList())
                {
                    Console.WriteLine($"S1={item.Q1},  Count={item.Q2},  Sum={item.Q3}");
                }
            }
        }     
    }

数据库中的数据:

结果:

 

看到查询类,也许你会想用系统的Tuple类进行查询,但Tuple类不能用作查询,两个原因:1.是Tuple缺少默认无参数构造函数;2.是Tuple类缺少Set属性,所以不适合。

 


猜你喜欢

转载自blog.csdn.net/wlk1229/article/details/79947848
今日推荐