版权声明:本文为博主原创文章,未经博主允许不得转载。 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属性,所以不适合。